12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529 |
- /**
- * from OimoPhysics DEV 1.1.0a AS3
- * @author Saharan / http://el-ement.com/
- *
- * to Oimo.js 2015 JAVASCRIPT
- * @author LoTh / http://lo-th.github.io/labs/
- */
- var OIMO = {
- REVISION: "1.2",
- // Global identification of next shape.
- // This will be incremented every time a shape is created.
- nextID: 0,
- proxyID: 0,
- // BroadPhase
- BR_NULL: 0,
- BR_BRUTE_FORCE: 1,
- BR_SWEEP_AND_PRUNE: 2,
- BR_BOUNDING_VOLUME_TREE: 3,
- // body type
- BODY_NULL: 0,
- BODY_DYNAMIC: 1,
- BODY_STATIC: 2,
- // shape type
- SHAPE_NULL: 0,
- SHAPE_SPHERE: 1,
- SHAPE_BOX: 2,
- SHAPE_CYLINDER: 3,
- SHAPE_TETRA: 4,
- // joint type
- JOINT_NULL: 0,
- JOINT_DISTANCE: 1,
- JOINT_BALL_AND_SOCKET: 2,
- JOINT_HINGE: 3,
- JOINT_WHEEL: 4,
- JOINT_SLIDER: 5,
- JOINT_PRISMATIC: 6,
- // this world scale defaut is 0.1 to 10 meters max for dynamique body
- // scale all by 100 so object is between 10 to 10000 three unit.
- WORLD_SCALE: 100,
- INV_SCALE: 0.01,
- // AABB aproximation
- AABB_PROX: 0.005,
- // Math function
- sqrt: Math.sqrt,
- abs: Math.abs,
- floor: Math.floor,
- cos: Math.cos,
- sin: Math.sin,
- acos: Math.acos,
- asin: Math.asin,
- atan2: Math.atan2,
- round: Math.round,
- pow: Math.pow,
- max: Math.max,
- min: Math.min,
- random: Math.random,
- lerp: function (a, b, percent) { return a + (b - a) * percent; },
- rand: function (a, b) { return OIMO.lerp(a, b, OIMO.random()); },
- randInt: function (a, b, n) { return OIMO.lerp(a, b, OIMO.random()).toFixed(n || 0) * 1; },
- int: function (x) { return ~~x; },
- fix: function (x, n) { return x.toFixed(n || 3, 10); },
- clamp: function (value, min, max) { return OIMO.max(min, OIMO.min(max, value)); },
- degtorad: 0.0174532925199432957,
- radtodeg: 57.295779513082320876,
- PI: 3.141592653589793,
- TwoPI: 6.283185307179586,
- PI90: 1.570796326794896,
- PI270: 4.712388980384689,
- CustomError: null,
- Error: function (Class, Msg) {
- if (OIMO.CustomError == null) console.error(Class, Msg);
- else OIMO.CustomError.innerHTML += Class + " - " + Msg + '<br>';
- }
- };
- var OIMO_ARRAY_TYPE;
- if (!OIMO_ARRAY_TYPE) { OIMO_ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array; }
- try {
- (function (w) {
- var perfNow;
- var perfNowNames = ['now', 'webkitNow', 'msNow', 'mozNow'];
- if (!!w['performance']) for (var i = 0; i < perfNowNames.length; ++i) {
- var n = perfNowNames[i];
- if (!!w['performance'][n]) {
- perfNow = function () { return w['performance'][n]() };
- break;
- }
- }
- if (!perfNow) perfNow = Date.now;
- //w.perfNow = perfNow;
- OIMO.now = perfNow;
- })(window);
- } catch (e) { OIMO.now = function () { return 0; }; }
- /**
- * The class of physical computing world.
- * You must be added to the world physical all computing objects
- * @author saharan
- * @author lo-th
- */
- OIMO.World = function (TimeStep, BroadPhaseType, Iterations, NoStat) {
- // The time between each step
- this.timeStep = TimeStep || 0.01666; // 1/60;
- // The number of iterations for constraint solvers.
- this.numIterations = Iterations || 8;
- // It is a wide-area collision judgment that is used in order to reduce as much as possible a detailed collision judgment.
- switch (BroadPhaseType || 2) {
- case 1: this.broadPhase = new OIMO.BruteForceBroadPhase(); break;
- case 2: default: this.broadPhase = new OIMO.SAPBroadPhase(); break;
- case 3: this.broadPhase = new OIMO.DBVTBroadPhase(); break;
- }
- // This is the detailed information of the performance.
- this.performance = null;
- this.isNoStat = NoStat || false;
- if (!this.isNoStat) this.performance = new OIMO.Performance(this);
- // Whether the constraints randomizer is enabled or not.
- this.enableRandomizer = true;
- // The rigid body list
- this.rigidBodies = null;
- // number of rigid body
- this.numRigidBodies = 0;
- // The contact list
- this.contacts = null;
- this.unusedContacts = null;
- // The number of contact
- this.numContacts = 0;
- // The number of contact points
- this.numContactPoints = 0;
- // The joint list
- this.joints = null;
- // The number of joints.
- this.numJoints = 0;
- // The number of simulation islands.
- this.numIslands = 0;
- // The gravity in the world.
- this.gravity = new OIMO.Vec3(0, -9.80665, 0);
- var numShapeTypes = 5;//4;//3;
- this.detectors = [];
- this.detectors.length = numShapeTypes;
- var i = numShapeTypes;
- while (i--) {
- this.detectors[i] = [];
- this.detectors[i].length = numShapeTypes;
- }
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_SPHERE] = new OIMO.SphereSphereCollisionDetector();
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_BOX] = new OIMO.SphereBoxCollisionDetector(false);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_SPHERE] = new OIMO.SphereBoxCollisionDetector(true);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_BOX] = new OIMO.BoxBoxCollisionDetector();
- // CYLINDER add
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_CYLINDER] = new OIMO.CylinderCylinderCollisionDetector();
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_BOX] = new OIMO.BoxCylinderCollisionDetector(true);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_CYLINDER] = new OIMO.BoxCylinderCollisionDetector(false);
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_SPHERE] = new OIMO.SphereCylinderCollisionDetector(true);
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_CYLINDER] = new OIMO.SphereCylinderCollisionDetector(false);
- // TETRA add
- this.detectors[OIMO.SHAPE_TETRA][OIMO.SHAPE_TETRA] = new OIMO.TetraTetraCollisionDetector();
- this.randX = 65535;
- this.randA = 98765;
- this.randB = 123456789;
- //this.maxIslandRigidBodies = 64;
- this.islandRigidBodies = [];
- //this.islandRigidBodies.length = this.maxIslandRigidBodies;
- this.islandStack = [];
- //this.islandStack.length = this.maxIslandRigidBodies;
- //this.maxIslandConstraints = 128;
- this.islandConstraints = [];
- //this.islandConstraints.length = this.maxIslandConstraints;
- };
- OIMO.World.prototype = {
- constructor: OIMO.World,
- /**
- * Reset the randomizer and remove all rigid bodies, shapes, joints and any object from the world.
- */
- clear: function () {
- this.randX = 65535;
- while (this.joints !== null) {
- this.removeJoint(this.joints);
- }
- while (this.contacts !== null) {
- this.removeContact(this.contacts);
- }
- while (this.rigidBodies !== null) {
- this.removeRigidBody(this.rigidBodies);
- }
- OIMO.nextID = 0;
- OIMO.proxyID = 0;
- },
- /**
- * I'll add a rigid body to the world.
- * Rigid body that has been added will be the operands of each step.
- * @param rigidBody Rigid body that you want to add
- */
- addRigidBody: function (rigidBody) {
- if (rigidBody.parent) {
- OIMO.Error("World", "It is not possible to be added to more than one world one of the rigid body");
- }
- rigidBody.parent = this;
- rigidBody.awake();
- for (var shape = rigidBody.shapes; shape !== null; shape = shape.next) {
- this.addShape(shape);
- }
- if (this.rigidBodies !== null) (this.rigidBodies.prev = rigidBody).next = this.rigidBodies;
- this.rigidBodies = rigidBody;
- this.numRigidBodies++;
- },
- /**
- * I will remove the rigid body from the world.
- * Rigid body that has been deleted is excluded from the calculation on a step-by-step basis.
- * @param rigidBody Rigid body to be removed
- */
- removeRigidBody: function (rigidBody) {
- var remove = rigidBody;
- if (remove.parent !== this) return;
- remove.awake();
- var js = remove.jointLink;
- while (js != null) {
- var joint = js.joint;
- js = js.next;
- this.removeJoint(joint);
- }
- for (var shape = rigidBody.shapes; shape !== null; shape = shape.next) {
- this.removeShape(shape);
- }
- var prev = remove.prev;
- var next = remove.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.rigidBodies == remove) this.rigidBodies = next;
- remove.prev = null;
- remove.next = null;
- remove.parent = null;
- this.numRigidBodies--;
- },
- getByName: function (name) {
- var result = null;
- var body = this.rigidBodies;
- while (body !== null) {
- if (body.name !== " " && body.name === name) result = body;
- body = body.next;
- }
- var joint = this.joints;
- while (joint !== null) {
- if (joint.name !== "" && joint.name === name) result = joint;
- joint = joint.next;
- }
- return result;
- },
- /**
- * I'll add a shape to the world..
- * Add to the rigid world, and if you add a shape to a rigid body that has been added to the world,
- * Shape will be added to the world automatically, please do not call from outside this method.
- * @param shape Shape you want to add
- */
- addShape: function (shape) {
- if (!shape.parent || !shape.parent.parent) {
- OIMO.Error("World", "It is not possible to be added alone to shape world");
- }
- shape.proxy = this.broadPhase.createProxy(shape);
- shape.updateProxy();
- this.broadPhase.addProxy(shape.proxy);
- },
- /**
- * I will remove the shape from the world.
- * Add to the rigid world, and if you add a shape to a rigid body that has been added to the world,
- * Shape will be added to the world automatically, please do not call from outside this method.
- * @param shape Shape you want to delete
- */
- removeShape: function (shape) {
- this.broadPhase.removeProxy(shape.proxy);
- shape.proxy = null;
- },
- /**
- * I'll add a joint to the world.
- * Joint that has been added will be the operands of each step.
- * @param shape Joint to be added
- */
- addJoint: function (joint) {
- if (joint.parent) {
- OIMO.Error("World", "It is not possible to be added to more than one world one of the joint");
- }
- if (this.joints != null) (this.joints.prev = joint).next = this.joints;
- this.joints = joint;
- joint.parent = this;
- this.numJoints++;
- joint.awake();
- joint.attach();
- },
- /**
- * I will remove the joint from the world.
- * Joint that has been added will be the operands of each step.
- * @param shape Joint to be deleted
- */
- removeJoint: function (joint) {
- var remove = joint;
- var prev = remove.prev;
- var next = remove.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.joints == remove) this.joints = next;
- remove.prev = null;
- remove.next = null;
- this.numJoints--;
- remove.awake();
- remove.detach();
- remove.parent = null;
- },
- worldscale: function (scale) {
- OIMO.WORLD_SCALE = scale || 100;
- OIMO.INV_SCALE = 1 / OIMO.WORLD_SCALE;
- },
- addContact: function (s1, s2) {
- var newContact;
- if (this.unusedContacts !== null) {
- newContact = this.unusedContacts;
- this.unusedContacts = this.unusedContacts.next;
- } else {
- newContact = new OIMO.Contact();
- }
- newContact.attach(s1, s2);
- newContact.detector = this.detectors[s1.type][s2.type];
- if (this.contacts) (this.contacts.prev = newContact).next = this.contacts;
- this.contacts = newContact;
- this.numContacts++;
- },
- removeContact: function (contact) {
- var prev = contact.prev;
- var next = contact.next;
- if (next) next.prev = prev;
- if (prev) prev.next = next;
- if (this.contacts == contact) this.contacts = next;
- contact.prev = null;
- contact.next = null;
- contact.detach();
- contact.next = this.unusedContacts;
- this.unusedContacts = contact;
- this.numContacts--;
- },
- checkContact: function (name1, name2) {
- var n1, n2;
- var contact = this.contacts;
- while (contact !== null) {
- n1 = contact.body1.name || ' ';
- n2 = contact.body2.name || ' ';
- if ((n1 == name1 && n2 == name2) || (n2 == name1 && n1 == name2)) { if (contact.touching) return true; else return false; }
- else contact = contact.next;
- }
- return false;
- },
- callSleep: function (body) {
- if (!body.allowSleep) return false;
- if (body.linearVelocity.lengthSq() > 0.04) return false;
- if (body.angularVelocity.lengthSq() > 0.25) return false;
- return true;
- },
- /**
- * I will proceed only time step seconds time of World.
- */
- step: function () {
- var time0, time1, time2, time3;
- var stat = !this.isNoStat ? true : false;
- if (stat) time0 = OIMO.now();
- var body = this.rigidBodies;
- while (body !== null) {
- body.addedToIsland = false;
- if (body.sleeping) {
- if (
- body.linearVelocity.testZero() ||
- body.angularVelocity.testZero() ||
- body.position.testDiff(body.sleepPosition) ||
- body.orientation.testDiff(body.sleepOrientation)
- ) body.awake(); // awake the body
- }
- body = body.next;
- }
- //------------------------------------------------------
- // UPDATE CONTACT
- //------------------------------------------------------
- // broad phase
- if (stat) time1 = OIMO.now();
- this.broadPhase.detectPairs();
- var pairs = this.broadPhase.pairs;
- var i = this.broadPhase.numPairs;
- //do{
- while (i--) {
- //for(var i=0, l=numPairs; i<l; i++){
- var pair = pairs[i];
- var s1;
- var s2;
- if (pair.shape1.id < pair.shape2.id) {
- s1 = pair.shape1;
- s2 = pair.shape2;
- } else {
- s1 = pair.shape2;
- s2 = pair.shape1;
- }
- var link;
- if (s1.numContacts < s2.numContacts) link = s1.contactLink;
- else link = s2.contactLink;
- var exists = false;
- while (link) {
- var contact = link.contact;
- if (contact.shape1 == s1 && contact.shape2 == s2) {
- contact.persisting = true;
- exists = true;// contact already exists
- break;
- }
- link = link.next;
- }
- if (!exists) {
- this.addContact(s1, s2);
- }
- }// while(i-- >0);
- if (stat) {
- time2 = OIMO.now();
- this.performance.broadPhaseTime = time2 - time1;
- }
- // update & narrow phase
- this.numContactPoints = 0;
- contact = this.contacts;
- while (contact !== null) {
- if (!contact.persisting) {
- if (contact.shape1.aabb.intersectTest(contact.shape2.aabb)) {
- /*var aabb1=contact.shape1.aabb;
- var aabb2=contact.shape2.aabb;
- if(
- aabb1.minX>aabb2.maxX || aabb1.maxX<aabb2.minX ||
- aabb1.minY>aabb2.maxY || aabb1.maxY<aabb2.minY ||
- aabb1.minZ>aabb2.maxZ || aabb1.maxZ<aabb2.minZ
- ){*/
- var next = contact.next;
- this.removeContact(contact);
- contact = next;
- continue;
- }
- }
- var b1 = contact.body1;
- var b2 = contact.body2;
- if (b1.isDynamic && !b1.sleeping || b2.isDynamic && !b2.sleeping) {
- contact.updateManifold();
- }
- this.numContactPoints += contact.manifold.numPoints;
- contact.persisting = false;
- contact.constraint.addedToIsland = false;
- contact = contact.next;
- }
- if (stat) {
- time3 = OIMO.now();
- this.performance.narrowPhaseTime = time3 - time2;
- }
- //------------------------------------------------------
- // SOLVE ISLANDS
- //------------------------------------------------------
- var invTimeStep = 1 / this.timeStep;
- //var body;
- var joint;
- var constraint;
- //var num;
- for (joint = this.joints; joint !== null; joint = joint.next) {
- joint.addedToIsland = false;
- }
- // clear old island array
- this.islandRigidBodies = [];
- this.islandConstraints = [];
- this.islandStack = [];
- // expand island buffers
- /*if(this.maxIslandRigidBodies<this.numRigidBodies){
- this.maxIslandRigidBodies=this.numRigidBodies<<1;
- //this.maxIslandRigidBodies=this.numRigidBodies*2;
- this.islandRigidBodies=[];
- this.islandStack=[];
- this.islandRigidBodies.length = this.maxIslandRigidBodies;
- this.islandStack.length = this.maxIslandRigidBodies;
- }
- var numConstraints=this.numJoints+this.numContacts;
- if(this.maxIslandConstraints<numConstraints){
- this.maxIslandConstraints=numConstraints<<1;
- //this.maxIslandConstraints=numConstraints*2;
- this.islandConstraints=[];
- this.islandConstraints.length = this.maxIslandConstraints;
- }*/
- time1 = OIMO.now();
- this.numIslands = 0;
- // build and solve simulation islands
- for (var base = this.rigidBodies; base !== null; base = base.next) {
- if (base.addedToIsland || base.isStatic || base.sleeping) continue;// ignore
- if (base.isLonely()) {// update single body
- if (base.isDynamic) {
- base.linearVelocity.addTime(this.gravity, this.timeStep);
- /*base.linearVelocity.x+=this.gravity.x*this.timeStep;
- base.linearVelocity.y+=this.gravity.y*this.timeStep;
- base.linearVelocity.z+=this.gravity.z*this.timeStep;*/
- }
- if (this.callSleep(base)) {
- base.sleepTime += this.timeStep;
- if (base.sleepTime > 0.5) base.sleep();
- else base.updatePosition(this.timeStep);
- } else {
- base.sleepTime = 0;
- base.updatePosition(this.timeStep);
- }
- this.numIslands++;
- continue;
- }
- var islandNumRigidBodies = 0;
- var islandNumConstraints = 0;
- var stackCount = 1;
- // add rigid body to stack
- this.islandStack[0] = base;
- base.addedToIsland = true;
- // build an island
- do {
- // get rigid body from stack
- body = this.islandStack[--stackCount];
- this.islandStack[stackCount] = null;
- body.sleeping = false;
- // add rigid body to the island
- this.islandRigidBodies[islandNumRigidBodies++] = body;
- if (body.isStatic) continue;
- // search connections
- for (var cs = body.contactLink; cs !== null; cs = cs.next) {
- var contact = cs.contact;
- constraint = contact.constraint;
- if (constraint.addedToIsland || !contact.touching) continue;// ignore
- // add constraint to the island
- this.islandConstraints[islandNumConstraints++] = constraint;
- constraint.addedToIsland = true;
- var next = cs.body;
- if (next.addedToIsland) continue;
- // add rigid body to stack
- this.islandStack[stackCount++] = next;
- next.addedToIsland = true;
- }
- for (var js = body.jointLink; js !== null; js = js.next) {
- constraint = js.joint;
- if (constraint.addedToIsland) continue;// ignore
- // add constraint to the island
- this.islandConstraints[islandNumConstraints++] = constraint;
- constraint.addedToIsland = true;
- next = js.body;
- if (next.addedToIsland || !next.isDynamic) continue;
- // add rigid body to stack
- this.islandStack[stackCount++] = next;
- next.addedToIsland = true;
- }
- } while (stackCount != 0);
- // update velocities
- var gVel = new OIMO.Vec3().addTime(this.gravity, this.timeStep);
- /*var gx=this.gravity.x*this.timeStep;
- var gy=this.gravity.y*this.timeStep;
- var gz=this.gravity.z*this.timeStep;*/
- var j = islandNumRigidBodies;
- while (j--) {
- //or(var j=0, l=islandNumRigidBodies; j<l; j++){
- body = this.islandRigidBodies[j];
- if (body.isDynamic) {
- body.linearVelocity.addEqual(gVel);
- /*body.linearVelocity.x+=gx;
- body.linearVelocity.y+=gy;
- body.linearVelocity.z+=gz;*/
- }
- }
- // randomizing order
- if (this.enableRandomizer) {
- //for(var j=1, l=islandNumConstraints; j<l; j++){
- j = islandNumConstraints;
- while (j--) {
- if (j !== 0) {
- var swap = (this.randX = (this.randX * this.randA + this.randB & 0x7fffffff)) / 2147483648.0 * j | 0;
- constraint = this.islandConstraints[j];
- this.islandConstraints[j] = this.islandConstraints[swap];
- this.islandConstraints[swap] = constraint;
- }
- }
- }
- // solve contraints
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, l=islandNumConstraints; j<l; j++){
- this.islandConstraints[j].preSolve(this.timeStep, invTimeStep);// pre-solve
- }
- var k = this.numIterations;
- while (k--) {
- //for(var k=0, l=this.numIterations; k<l; k++){
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, m=islandNumConstraints; j<m; j++){
- this.islandConstraints[j].solve();// main-solve
- }
- }
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, l=islandNumConstraints; j<l; j++){
- this.islandConstraints[j].postSolve();// post-solve
- this.islandConstraints[j] = null;// gc
- }
- // sleeping check
- var sleepTime = 10;
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- body = this.islandRigidBodies[j];
- if (this.callSleep(body)) {
- body.sleepTime += this.timeStep;
- if (body.sleepTime < sleepTime) sleepTime = body.sleepTime;
- } else {
- body.sleepTime = 0;
- sleepTime = 0;
- continue;
- }
- }
- if (sleepTime > 0.5) {
- // sleep the island
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- this.islandRigidBodies[j].sleep();
- this.islandRigidBodies[j] = null;// gc
- }
- } else {
- // update positions
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- this.islandRigidBodies[j].updatePosition(this.timeStep);
- this.islandRigidBodies[j] = null;// gc
- }
- }
- this.numIslands++;
- }
- if (stat) {
- time2 = OIMO.now();
- this.performance.solvingTime = time2 - time1;
- //------------------------------------------------------
- // END SIMULATION
- //------------------------------------------------------
- time2 = OIMO.now();
- // fps update
- this.performance.upfps();
- this.performance.totalTime = time2 - time0;
- }
- }
- }
- /**
- * The class of rigid body.
- * Rigid body has the shape of a single or multiple collision processing,
- * I can set the parameters individually.
- * @author saharan
- */
- OIMO.RigidBody = function (x, y, z, rad, ax, ay, az) {
- this.name = " ";
- // The maximum number of shapes that can be added to a one rigid.
- this.MAX_SHAPES = 64;//64;
- this.prev = null;
- this.next = null;
- // I represent the kind of rigid body.
- // Please do not change from the outside this variable.
- // If you want to change the type of rigid body, always
- // Please specify the type you want to set the arguments of setupMass method.
- this.type = OIMO.BODY_NULL;
- this.massInfo = new OIMO.MassInfo();
- // It is the world coordinate of the center of gravity.
- this.position = new OIMO.Vec3(x, y, z);
- this.orientation = this.rotationAxisToQuad(rad || 0, ax || 0, ay || 0, az || 0);
- this.newPosition = new OIMO.Vec3();
- this.controlPos = false;
- this.newOrientation = new OIMO.Quat();
- this.newRotation = new OIMO.Vec3();
- this.currentRotation = new OIMO.Vec3();
- this.controlRot = false;
- this.controlRotInTime = false;
- // Is the translational velocity.
- this.linearVelocity = new OIMO.Vec3();
- // Is the angular velocity.
- this.angularVelocity = new OIMO.Vec3();
- // return matrix for three.js
- this.matrix = new OIMO.Mat44();
- //--------------------------------------------
- // Please do not change from the outside this variables.
- //--------------------------------------------
- // It is a world that rigid body has been added.
- this.parent = null;
- this.contactLink = null;
- this.numContacts = 0;
- // An array of shapes that are included in the rigid body.
- this.shapes = null;
- // The number of shapes that are included in the rigid body.
- this.numShapes = 0;
- // It is the link array of joint that is connected to the rigid body.
- this.jointLink = null;
- // The number of joints that are connected to the rigid body.
- this.numJoints = 0;
- // It is the world coordinate of the center of gravity in the sleep just before.
- this.sleepPosition = new OIMO.Vec3();
- // It is a quaternion that represents the attitude of sleep just before.
- this.sleepOrientation = new OIMO.Quat();
- // I will show this rigid body to determine whether it is a rigid body static.
- this.isStatic = false;
- // I indicates that this rigid body to determine whether it is a rigid body dynamic.
- this.isDynamic = false;
- // It is a rotation matrix representing the orientation.
- this.rotation = new OIMO.Mat33();
- //--------------------------------------------
- // It will be recalculated automatically from the shape, which is included.
- //--------------------------------------------
- // This is the weight.
- this.mass = NaN;
- // It is the reciprocal of the mass.
- this.inverseMass = NaN;
- // It is the inverse of the inertia tensor in the world system.
- this.inverseInertia = new OIMO.Mat33();
- // It is the inertia tensor in the initial state.
- this.localInertia = new OIMO.Mat33();
- // It is the inverse of the inertia tensor in the initial state.
- this.inverseLocalInertia = new OIMO.Mat33();
- // I indicates rigid body whether it has been added to the simulation Island.
- this.addedToIsland = false;
- // It shows how to sleep rigid body.
- this.allowSleep = true;
- // This is the time from when the rigid body at rest.
- this.sleepTime = 0;
- // I shows rigid body to determine whether it is a sleep state.
- this.sleeping = false;
- };
- OIMO.RigidBody.prototype = {
- constructor: OIMO.RigidBody,
- /**
- * I'll add a shape to rigid body.
- * If you add a shape, please call the setupMass method to step up to the start of the next.
- * @param shape shape to Add
- */
- addShape: function (shape) {
- if (shape.parent) OIMO.Error("RigidBody", "It is not possible that you add to the multi-rigid body the shape of one");
- if (this.shapes != null) (this.shapes.prev = shape).next = this.shapes;
- this.shapes = shape;
- shape.parent = this;
- if (this.parent) this.parent.addShape(shape);
- this.numShapes++;
- },
- /**
- * I will delete the shape from the rigid body.
- * If you delete a shape, please call the setupMass method to step up to the start of the next.
- * @param shape shape to Delete
- */
- removeShape: function (shape) {
- var remove = shape;
- if (remove.parent != this) return;
- var prev = remove.prev;
- var next = remove.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.shapes == remove) this.shapes = next;
- remove.prev = null;
- remove.next = null;
- remove.parent = null;
- if (this.parent) this.parent.removeShape(remove);
- this.numShapes--;
- },
- remove: function () {
- this.dispose();
- },
- dispose: function () {
- this.parent.removeRigidBody(this);
- },
- checkContact: function (name) {
- this.parent.checkContact(this.name, name);
- },
- /**
- * Calulates mass datas(center of gravity, mass, moment inertia, etc...).
- * If the parameter type is set to BODY_STATIC, the rigid body will be fixed to the space.
- * If the parameter adjustPosition is set to true, the shapes' relative positions and
- * the rigid body's position will be adjusted to the center of gravity.
- * @param type
- * @param adjustPosition
- */
- setupMass: function (type, AdjustPosition) {
- var adjustPosition = (AdjustPosition !== undefined) ? AdjustPosition : true;
- this.type = type || OIMO.BODY_DYNAMIC;
- this.isDynamic = this.type == OIMO.BODY_DYNAMIC;
- this.isStatic = this.type == OIMO.BODY_STATIC;
- this.mass = 0;
- this.localInertia.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
- var te = this.localInertia.elements;
- //
- var tmpM = new OIMO.Mat33();
- var tmpV = new OIMO.Vec3();
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.calculateMassInfo(this.massInfo);
- var shapeMass = this.massInfo.mass;
- var relX = shape.relativePosition.x;
- var relY = shape.relativePosition.y;
- var relZ = shape.relativePosition.z;
- /*tmpV.x+=relX*shapeMass;
- tmpV.y+=relY*shapeMass;
- tmpV.z+=relZ*shapeMass;*/
- tmpV.addScale(shape.relativePosition, shapeMass);
- this.mass += shapeMass;
- this.rotateInertia(shape.relativeRotation, this.massInfo.inertia, tmpM);
- this.localInertia.addEqual(tmpM);
- // add offset inertia
- te[0] += shapeMass * (relY * relY + relZ * relZ);
- te[4] += shapeMass * (relX * relX + relZ * relZ);
- te[8] += shapeMass * (relX * relX + relY * relY);
- var xy = shapeMass * relX * relY;
- var yz = shapeMass * relY * relZ;
- var zx = shapeMass * relZ * relX;
- te[1] -= xy;
- te[3] -= xy;
- te[2] -= yz;
- te[6] -= yz;
- te[5] -= zx;
- te[7] -= zx;
- }
- this.inverseMass = 1 / this.mass;
- tmpV.scaleEqual(this.inverseMass);
- if (adjustPosition) {
- this.position.addEqual(tmpV);
- for (shape = this.shapes; shape != null; shape = shape.next) {
- shape.relativePosition.subEqual(tmpV);
- }
- // subtract offset inertia
- relX = tmpV.x;
- relY = tmpV.y;
- relZ = tmpV.z;
- //var te = this.localInertia.elements;
- te[0] -= this.mass * (relY * relY + relZ * relZ);
- te[4] -= this.mass * (relX * relX + relZ * relZ);
- te[8] -= this.mass * (relX * relX + relY * relY);
- xy = this.mass * relX * relY;
- yz = this.mass * relY * relZ;
- zx = this.mass * relZ * relX;
- te[1] += xy;
- te[3] += xy;
- te[2] += yz;
- te[6] += yz;
- te[5] += zx;
- te[7] += zx;
- }
- this.inverseLocalInertia.invert(this.localInertia);
- if (this.type == OIMO.BODY_STATIC) {
- this.inverseMass = 0;
- this.inverseLocalInertia.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
- }
- this.syncShapes();
- this.awake();
- },
- /**
- * Awake the rigid body.
- */
- awake: function () {
- if (!this.allowSleep || !this.sleeping) return;
- this.sleeping = false;
- this.sleepTime = 0;
- // awake connected constraints
- var cs = this.contactLink;
- while (cs != null) {
- cs.body.sleepTime = 0;
- cs.body.sleeping = false;
- cs = cs.next;
- }
- var js = this.jointLink;
- while (js != null) {
- js.body.sleepTime = 0;
- js.body.sleeping = false;
- js = js.next;
- }
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.updateProxy();
- }
- },
- /**
- * Sleep the rigid body.
- */
- sleep: function () {
- if (!this.allowSleep || this.sleeping) return;
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- this.sleepPosition.copy(this.position);
- this.sleepOrientation.copy(this.orientation);
- /*this.linearVelocity.x=0;
- this.linearVelocity.y=0;
- this.linearVelocity.z=0;
- this.angularVelocity.x=0;
- this.angularVelocity.y=0;
- this.angularVelocity.z=0;
- this.sleepPosition.x=this.position.x;
- this.sleepPosition.y=this.position.y;
- this.sleepPosition.z=this.position.z;*/
- /*this.sleepOrientation.s=this.orientation.s;
- this.sleepOrientation.x=this.orientation.x;
- this.sleepOrientation.y=this.orientation.y;
- this.sleepOrientation.z=this.orientation.z;*/
- this.sleepTime = 0;
- this.sleeping = true;
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.updateProxy();
- }
- },
- /**
- * Get whether the rigid body has not any connection with others.
- * @return
- */
- isLonely: function () {
- return this.numJoints == 0 && this.numContacts == 0;
- },
- /**
- * The time integration of the motion of a rigid body, you can update the information such as the shape.
- * This method is invoked automatically when calling the step of the World,
- * There is no need to call from outside usually.
- * @param timeStep time
- */
- updatePosition: function (timeStep) {
- switch (this.type) {
- case OIMO.BODY_STATIC:
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- // ONLY FOR TEST
- if (this.controlPos) {
- this.position.copy(this.newPosition);
- this.controlPos = false;
- }
- if (this.controlRot) {
- this.orientation.copy(this.newOrientation);
- this.controlRot = false;
- }
- /*this.linearVelocity.x=0;
- this.linearVelocity.y=0;
- this.linearVelocity.z=0;
- this.angularVelocity.x=0;
- this.angularVelocity.y=0;
- this.angularVelocity.z=0;*/
- break;
- case OIMO.BODY_DYNAMIC:
- if (this.controlPos) {
- this.angularVelocity.set(0, 0, 0);
- this.linearVelocity.set(0, 0, 0);
- this.linearVelocity.x = (this.newPosition.x - this.position.x) / timeStep;
- this.linearVelocity.y = (this.newPosition.y - this.position.y) / timeStep;
- this.linearVelocity.z = (this.newPosition.z - this.position.z) / timeStep;
- this.controlPos = false;
- }
- if (this.controlRot) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation.copy(this.newOrientation);
- //var t=timeStep//*0.5;
- //var q = new OIMO.Quat();
- //q.sub(this.newOrientation, this.orientation);
- //q.normalize(q);
- /*q.s = (this.newOrientation.s - this.orientation.s)/t;
- q.x = (this.newOrientation.x - this.orientation.x)/t;
- q.y = (this.newOrientation.y - this.orientation.y)/t;
- q.z = (this.newOrientation.z - this.orientation.z)/t;*/
- //this.angularVelocity.applyQuaternion(q);
- //this.angularVelocity.x = this.angularVelocity.x/t;
- //this.angularVelocity.y = this.angularVelocity.y/t;
- //this.angularVelocity.z = this.angularVelocity.z/t;
- this.controlRot = false;
- }
- this.position.addTime(this.linearVelocity, timeStep);
- this.orientation.addTime(this.angularVelocity, timeStep);
- break;
- default: OIMO.Error("RigidBody", "Invalid type.");
- }
- this.syncShapes();
- },
- rotateInertia: function (rot, inertia, out) {
- var tm1 = rot.elements;
- var tm2 = inertia.elements;
- var a0 = tm1[0], a3 = tm1[3], a6 = tm1[6];
- var a1 = tm1[1], a4 = tm1[4], a7 = tm1[7];
- var a2 = tm1[2], a5 = tm1[5], a8 = tm1[8];
- var b0 = tm2[0], b3 = tm2[3], b6 = tm2[6];
- var b1 = tm2[1], b4 = tm2[4], b7 = tm2[7];
- var b2 = tm2[2], b5 = tm2[5], b8 = tm2[8];
- var e00 = a0 * b0 + a1 * b3 + a2 * b6;
- var e01 = a0 * b1 + a1 * b4 + a2 * b7;
- var e02 = a0 * b2 + a1 * b5 + a2 * b8;
- var e10 = a3 * b0 + a4 * b3 + a5 * b6;
- var e11 = a3 * b1 + a4 * b4 + a5 * b7;
- var e12 = a3 * b2 + a4 * b5 + a5 * b8;
- var e20 = a6 * b0 + a7 * b3 + a8 * b6;
- var e21 = a6 * b1 + a7 * b4 + a8 * b7;
- var e22 = a6 * b2 + a7 * b5 + a8 * b8;
- var oe = out.elements;
- oe[0] = e00 * a0 + e01 * a1 + e02 * a2;
- oe[1] = e00 * a3 + e01 * a4 + e02 * a5;
- oe[2] = e00 * a6 + e01 * a7 + e02 * a8;
- oe[3] = e10 * a0 + e11 * a1 + e12 * a2;
- oe[4] = e10 * a3 + e11 * a4 + e12 * a5;
- oe[5] = e10 * a6 + e11 * a7 + e12 * a8;
- oe[6] = e20 * a0 + e21 * a1 + e22 * a2;
- oe[7] = e20 * a3 + e21 * a4 + e22 * a5;
- oe[8] = e20 * a6 + e21 * a7 + e22 * a8;
- },
- syncShapes: function () {
- var s = this.orientation.s;
- var x = this.orientation.x;
- var y = this.orientation.y;
- var z = this.orientation.z;
- var x2 = 2 * x;
- var y2 = 2 * y;
- var z2 = 2 * z;
- var xx = x * x2;
- var yy = y * y2;
- var zz = z * z2;
- var xy = x * y2;
- var yz = y * z2;
- var xz = x * z2;
- var sx = s * x2;
- var sy = s * y2;
- var sz = s * z2;
- var tr = this.rotation.elements;
- tr[0] = 1 - yy - zz;
- tr[1] = xy - sz;
- tr[2] = xz + sy;
- tr[3] = xy + sz;
- tr[4] = 1 - xx - zz;
- tr[5] = yz - sx;
- tr[6] = xz - sy;
- tr[7] = yz + sx;
- tr[8] = 1 - xx - yy;
- this.rotateInertia(this.rotation, this.inverseLocalInertia, this.inverseInertia);
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- //var relPos=shape.relativePosition;
- //var relRot=shape.relativeRotation;
- //var rot=shape.rotation;
- /*var lx=relPos.x;
- var ly=relPos.y;
- var lz=relPos.z;
- shape.position.x=this.position.x+lx*tr[0]+ly*tr[1]+lz*tr[2];
- shape.position.y=this.position.y+lx*tr[3]+ly*tr[4]+lz*tr[5];
- shape.position.z=this.position.z+lx*tr[6]+ly*tr[7]+lz*tr[8];*/
- shape.position.mul(this.position, shape.relativePosition, this.rotation);
- //shape.rotation.mul(shape.relativeRotation,this.rotation);
- // add by QuaziKb
- shape.rotation.mul(this.rotation, shape.relativeRotation);
- shape.updateProxy();
- }
- },
- applyImpulse: function (position, force) {
- this.linearVelocity.addScale(force, this.inverseMass);
- /*this.linearVelocity.x+=force.x*this.inverseMass;
- this.linearVelocity.y+=force.y*this.inverseMass;
- this.linearVelocity.z+=force.z*this.inverseMass;*/
- var rel = new OIMO.Vec3();
- rel.sub(position, this.position).cross(rel, force).mulMat(this.inverseInertia, rel);
- this.angularVelocity.addEqual(rel);
- /*this.angularVelocity.x+=rel.x;
- this.angularVelocity.y+=rel.y;
- this.angularVelocity.z+=rel.z;*/
- },
- //---------------------------------------------
- //
- // FOR THREE JS
- //
- //---------------------------------------------
- rotationVectToQuad: function (rot) {
- var r = OIMO.EulerToAxis(rot.x * OIMO.degtorad, rot.y * OIMO.degtorad, rot.z * OIMO.degtorad);
- return this.rotationAxisToQuad(r[0], r[1], r[2], r[3]);
- },
- rotationAxisToQuad: function (rad, ax, ay, az) { // in radian
- var len = ax * ax + ay * ay + az * az;
- if (len > 0) {
- len = 1 / OIMO.sqrt(len);
- ax *= len;
- ay *= len;
- az *= len;
- }
- var sin = OIMO.sin(rad * 0.5);
- var cos = OIMO.cos(rad * 0.5);
- return new OIMO.Quat(cos, sin * ax, sin * ay, sin * az);
- },
- //---------------------------------------------
- // SET DYNAMIQUE POSITION AND ROTATION
- //---------------------------------------------
- setPosition: function (pos) {
- this.newPosition.copy(pos).multiplyScalar(OIMO.INV_SCALE);
- //this.newPosition.set(pos.x*OIMO.INV_SCALE,pos.y*OIMO.INV_SCALE,pos.z*OIMO.INV_SCALE);
- this.controlPos = true;
- },
- setQuaternion: function (q) {
- //if(this.type == this.BODY_STATIC)this.orientation.init(q.w,q.x,q.y,q.z);
- this.newOrientation.set(q.x, q.y, q.z, q.w);
- this.controlRot = true;
- },
- setRotation: function (rot) {
- this.newOrientation = this.rotationVectToQuad(rot);
- this.controlRot = true;
- },
- //---------------------------------------------
- // RESET DYNAMIQUE POSITION AND ROTATION
- //---------------------------------------------
- resetPosition: function (x, y, z) {
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- this.position.set(x, y, z).multiplyScalar(OIMO.INV_SCALE);
- //this.position.set( x*OIMO.INV_SCALE, y*OIMO.INV_SCALE, z*OIMO.INV_SCALE );
- this.awake();
- },
- resetQuaternion: function (q) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation = new OIMO.Quat(q.w, q.x, q.y, q.z);
- this.awake();
- },
- resetRotation: function (x, y, z) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation = this.rotationVectToQuad(new OIMO.Vec3(x, y, z));
- this.awake();
- },
- //---------------------------------------------
- // GET POSITION AND ROTATION
- //---------------------------------------------
- getPosition: function () {
- return new OIMO.Vec3().scale(this.position, OIMO.WORLD_SCALE);
- },
- getRotation: function () {
- return new OIMO.Euler().setFromRotationMatrix(this.rotation);
- },
- getQuaternion: function () {
- return new OIMO.Quaternion().setFromRotationMatrix(this.rotation);
- },
- getMatrix: function () {
- var m = this.matrix.elements;
- var r, p;
- if (!this.sleeping) {
- // rotation matrix
- r = this.rotation.elements;
- m[0] = r[0]; m[1] = r[3]; m[2] = r[6]; m[3] = 0;
- m[4] = r[1]; m[5] = r[4]; m[6] = r[7]; m[7] = 0;
- m[8] = r[2]; m[9] = r[5]; m[10] = r[8]; m[11] = 0;
- // position matrix
- p = this.position;
- m[12] = p.x * OIMO.WORLD_SCALE;
- m[13] = p.y * OIMO.WORLD_SCALE;
- m[14] = p.z * OIMO.WORLD_SCALE;
- // sleep or not ?
- m[15] = 0;
- } else {
- m[15] = 1;
- }
- return m;
- }
- };
- /**
- * The main class of body.
- * is for simplify creation process and data access of rigidRody
- * Rigid body has the shape of a single or multiple collision processing,
- * all setting in object
- *
- * @author loth
- */
- OIMO.Body = function (Obj) {
- var obj = Obj || {};
- if (!obj.world) return;
- if (obj.type === undefined) obj.type = "box";
- this.name = obj.name || '';
- // obsolete use world.add(obj)
- this.body = obj.world.add(obj);
- /*
- // the world where i am
- this.parent = obj.world;
-
- // Yep my name
- this.name = obj.name || '';
-
- // I'm dynamique or not
- var move = obj.move || false;
-
- // I can sleep or not
- var noSleep = obj.noSleep || false;
-
- // My start position
- var p = obj.pos || [0,0,0];
- p = p.map(function(x) { return x * OIMO.INV_SCALE; });
-
- // My size
- var s = obj.size || [1,1,1];
- s = s.map(function(x) { return x * OIMO.INV_SCALE; });
-
- // My rotation in degre
- var rot = obj.rot || [0,0,0];
- rot = rot.map(function(x) { return x * OIMO.TO_RAD; });
- var r = [];
- for (var i=0; i<rot.length/3; i++){
- var tmp = OIMO.EulerToAxis(rot[i+0], rot[i+1], rot[i+2]);
- r.push(tmp[0]); r.push(tmp[1]); r.push(tmp[2]); r.push(tmp[3]);
- }
-
- // My physics setting
- var sc = obj.sc || new OIMO.ShapeConfig();
- if(obj.config){
- // The density of the shape.
- sc.density = obj.config[0] || 1;
- // The coefficient of friction of the shape.
- sc.friction = obj.config[1] || 0.4;
- // The coefficient of restitution of the shape.
- sc.restitution = obj.config[2] || 0.2;
- // The bits of the collision groups to which the shape belongs.
- sc.belongsTo = obj.config[3] || 1;
- // The bits of the collision groups with which the shape collides.
- sc.collidesWith = obj.config[4] || 0xffffffff;
- }
-
- if(obj.massPos){
- obj.massPos = obj.massPos.map(function(x) { return x * OIMO.INV_SCALE; });
- sc.relativePosition.init(obj.massPos[0], obj.massPos[1], obj.massPos[2]);
- }
- if(obj.massRot){
- obj.massRot = obj.massRot.map(function(x) { return x * OIMO.TO_RAD; });
- sc.relativeRotation = OIMO.EulerToMatrix(obj.massRot[0], obj.massRot[1], obj.massRot[2]);
- }
-
- // My rigidbody
- this.body = new OIMO.RigidBody(p[0], p[1], p[2], r[0], r[1], r[2], r[3]);
-
- // My shapes
- var shapes = [];
- var type = obj.type || "box";
- if( typeof type === 'string' ) type = [type];// single shape
-
- var n, n2;
- for(var i=0; i<type.length; i++){
- n = i*3;
- n2 = i*4;
- switch(type[i]){
- case "sphere": shapes[i] = new OIMO.SphereShape(sc, s[n+0]); break;
- case "cylinder": shapes[i] = new OIMO.BoxShape(sc, s[n+0], s[n+1], s[n+2]); break; // fake cylinder
- case "box": shapes[i] = new OIMO.BoxShape(sc, s[n+0], s[n+1], s[n+2]); break;
- }
- this.body.addShape(shapes[i]);
- if(i>0){
- //shapes[i].position.init(p[0]+p[n+0], p[1]+p[n+1], p[2]+p[n+2] );
- shapes[i].relativePosition = new OIMO.Vec3( p[n+0], p[n+1], p[n+2] );
- if(r[n2+0]) shapes[i].relativeRotation = [ r[n2+0], r[n2+1], r[n2+2], r[n2+3] ];
- }
- }
-
- // I'm static or i move
- if(move){
- if(obj.massPos || obj.massRot)this.body.setupMass(0x1, false);
- else this.body.setupMass(0x1, true);
- if(noSleep) this.body.allowSleep = false;
- else this.body.allowSleep = true;
- } else {
- this.body.setupMass(0x2);
- }
-
- this.body.name = this.name;
- this.sleeping = this.body.sleeping;
-
- // finaly add to physics world
- this.parent.addRigidBody(this.body);*/
- }
- OIMO.Body.prototype = {
- constructor: OIMO.Body,
- // SET
- setPosition: function (pos) {
- this.body.setPosition(pos);
- },
- setQuaternion: function (q) {
- this.body.setQuaternion(q);
- },
- setRotation: function (rot) {
- this.body.setRotation(rot);
- },
- // GET
- getPosition: function () {
- return this.body.getPosition();
- },
- getRotation: function () {
- return this.body.getRotation();
- },
- getQuaternion: function () {
- return this.body.getQuaternion();
- },
- getMatrix: function () {
- return this.body.getMatrix();
- },
- getSleep: function () {
- return this.body.sleeping;
- },
- // RESET
- resetPosition: function (x, y, z) {
- this.body.resetPosition(x, y, z);
- },
- resetRotation: function (x, y, z) {
- this.body.resetRotation(x, y, z);
- },
- // force wakeup
- awake: function () {
- this.body.awake();
- },
- // remove rigidbody
- remove: function () {
- this.body.dispose();
- //this.parent.removeRigidBody(this.body);
- },
- // test if this object hit another
- checkContact: function (name) {
- this.body.checkContact(name);
- //this.parent.checkContact(this.name, name);
- }
- }
- /**
- * The main class of link.
- * is for simplify creation process and data access of Joint
- * all setting in object
- *
- * @author loth
- */
- OIMO.Link = function (Obj) {
- var obj = Obj || {};
- if (!obj.world) return;
- if (obj.type === undefined) obj.type = "jointHinge";
- this.name = obj.name || '';
- // obsolete use world.add(obj)
- this.joint = obj.world.add(obj);
- // the world where i am
- /*this.parent = obj.world;
- this.name = obj.name || '';
- var type = obj.type || "jointHinge";
- var axe1 = obj.axe1 || [1,0,0];
- var axe2 = obj.axe2 || [1,0,0];
- var pos1 = obj.pos1 || [0,0,0];
- var pos2 = obj.pos2 || [0,0,0];
- pos1 = pos1.map(function(x){ return x * OIMO.INV_SCALE; });
- pos2 = pos2.map(function(x){ return x * OIMO.INV_SCALE; });
- var min, max;
- if(type==="jointDistance"){
- min = obj.min || 0;
- max = obj.max || 10;
- min = min*OIMO.INV_SCALE;
- max = max*OIMO.INV_SCALE;
- }else{
- min = obj.min || 57.29578;
- max = obj.max || 0;
- min = min*OIMO.TO_RAD;
- max = max*OIMO.TO_RAD;
- }
- var limit = obj.limit || null;
- var spring = obj.spring || null;
- var motor = obj.motor || null;
- // joint setting
- var jc = new OIMO.JointConfig();
- jc.allowCollision = obj.collision || false;;
- jc.localAxis1.init(axe1[0], axe1[1], axe1[2]);
- jc.localAxis2.init(axe2[0], axe2[1], axe2[2]);
- jc.localAnchorPoint1.init(pos1[0], pos1[1], pos1[2]);
- jc.localAnchorPoint2.init(pos2[0], pos2[1], pos2[2]);
- if (typeof obj.body1 == 'string' || obj.body1 instanceof String) obj.body1 = obj.world.getByName(obj.body1);
- if (typeof obj.body2 == 'string' || obj.body2 instanceof String) obj.body2 = obj.world.getByName(obj.body2);
- jc.body1 = obj.body1;
- jc.body2 = obj.body2;
-
- switch(type){
- case "jointDistance": this.joint = new OIMO.DistanceJoint(jc, min, max);
- if(spring !== null) this.joint.limitMotor.setSpring(spring[0], spring[1]);
- if(motor !== null) this.joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointHinge": this.joint = new OIMO.HingeJoint(jc, min, max);
- if(spring !== null) this.joint.limitMotor.setSpring(spring[0], spring[1]);// soften the joint ex: 100, 0.2
- if(motor !== null) this.joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointPrisme": this.joint = new OIMO.PrismaticJoint(jc, min, max); break;
- case "jointSlide": this.joint = new OIMO.SliderJoint(jc, min, max); break;
- case "jointBall": this.joint = new OIMO.BallAndSocketJoint(jc); break;
- case "jointWheel": this.joint = new OIMO.WheelJoint(jc);
- if(limit !== null) this.joint.rotationalLimitMotor1.setLimit(limit[0], limit[1]);
- if(spring !== null) this.joint.rotationalLimitMotor1.setSpring(spring[0], spring[1]);
- if(motor !== null) this.joint.rotationalLimitMotor1.setSpring(motor[0], motor[1]);
- break;
- }
- this.joint.name = this.name;
-
- // finaly add to physics world
- this.parent.addJoint(this.joint);*/
- }
- OIMO.Link.prototype = {
- constructor: OIMO.Link,
- getPosition: function () {
- // array of two vect3 [point1, point2]
- return this.joint.getPosition();
- },
- getMatrix: function () {
- return this.joint.getMatrix();
- },
- // remove joint
- remove: function () {
- this.joint.dispose();
- //this.parent.removeJoint(this.joint);
- },
- // force wakeup linked body
- awake: function () {
- this.joint.awake();
- }
- }
- /**
- * The Dictionary class for testing
- * @author lo-th
- */
- OIMO.Dictionary = function () {
- this.data = {};
- this.keys = [];
- };
- OIMO.Dictionary.prototype = {
- constructor: OIMO.Dictionary,
- set: function (value) {
- var key = value.id;
- if (!this.get[key]) this.keys.push(key);
- this.data[key] = value;
- },
- get: function (id) {
- return this.data[id];
- },
- del: function (value) {
- var k = this.keys;
- var n = k.indexOf(value.id);
- if (n > -1) {
- delete this.data[k[n]];
- k.splice(n, 1);
- }
- },
- reset: function () {
- var data = this.data, keys = this.keys, key;
- while (keys.length > 0) {
- key = keys.pop();
- delete data[key];
- }
- }
- };
- OIMO.Performance = function (world) {
- this.parent = world;
- this.infos = new OIMO_ARRAY_TYPE(13);
- this.f = [0, 0, 0];
- this.types = ['None', 'BruteForce', 'Sweep & Prune', 'Bounding Volume Tree'];
- this.broadPhase = this.types[this.parent.broadPhase.types];
- this.version = OIMO.REVISION;
- this.fps = 0;
- this.broadPhaseTime = 0;
- this.narrowPhaseTime = 0;
- this.solvingTime = 0;
- //this.updatingTime = 0;
- this.totalTime = 0;
- };
- OIMO.Performance.prototype = {
- upfps: function () {
- this.f[1] = Date.now();
- if (this.f[1] - 1000 > this.f[0]) { this.f[0] = this.f[1]; this.fps = this.f[2]; this.f[2] = 0; } this.f[2]++;
- },
- updatingTime: function () {
- return OIMO.fix(this.totalTime - (this.broadPhaseTime + this.narrowPhaseTime + this.solvingTime));
- },
- show: function () {
- var info = [
- "Oimo.js " + this.version + "<br>",
- this.broadPhase + "<br><br>",
- "FPS: " + this.fps + " fps<br><br>",
- "rigidbody " + this.parent.numRigidBodies + "<br>",
- "contact " + this.parent.numContacts + "<br>",
- "ct-point " + this.parent.numContactPoints + "<br>",
- "paircheck " + this.parent.broadPhase.numPairChecks + "<br>",
- "island " + this.parent.numIslands + "<br><br>",
- "Time in milliseconde<br><br>",
- "broad-phase " + OIMO.fix(this.broadPhaseTime) + "<br>",
- "narrow-phase " + OIMO.fix(this.narrowPhaseTime) + "<br>",
- "solving " + OIMO.fix(this.solvingTime) + "<br>",
- "total " + OIMO.fix(this.totalTime) + "<br>",
- "updating " + this.updatingTime() + "<br>"
- ].join("\n");
- return info;
- },
- toArray: function () {
- this.infos[0] = this.parent.broadPhase.types;
- this.infos[1] = this.parent.numRigidBodies;
- this.infos[2] = this.parent.numContacts;
- this.infos[3] = this.parent.broadPhase.numPairChecks;
- this.infos[4] = this.parent.numContactPoints;
- this.infos[5] = this.parent.numIslands;
- this.infos[6] = this.broadPhaseTime;
- this.infos[7] = this.narrowPhaseTime;
- this.infos[8] = this.solvingTime;
- this.infos[9] = this.updatingTime();
- this.infos[10] = this.totalTime;
- this.infos[11] = this.fps;
- return this.infos;
- }
- };
- OIMO.Mat44 = function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
- this.elements = new OIMO_ARRAY_TYPE(16);
- var te = this.elements;
- te[0] = (n11 !== undefined) ? n11 : 1; te[4] = n12 || 0; te[8] = n13 || 0; te[12] = n14 || 0;
- te[1] = n21 || 0; te[5] = (n22 !== undefined) ? n22 : 1; te[9] = n23 || 0; te[13] = n24 || 0;
- te[2] = n31 || 0; te[6] = n32 || 0; te[10] = (n33 !== undefined) ? n33 : 1; te[14] = n34 || 0;
- te[3] = n41 || 0; te[7] = n42 || 0; te[11] = n43 || 0; te[15] = (n44 !== undefined) ? n44 : 1;
- };
- OIMO.Mat44.prototype = {
- constructor: OIMO.Mat44,
- set: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
- var te = this.elements;
- te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
- te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
- te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
- te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
- return this;
- }/*,
- extractRotation: function () {
- var v1 = new THREE.Vector3();
- return function ( m ) {
- var te = this.elements;
- var me = m.elements;
- var scaleX = 1 / v1.set( me[ 0 ], me[ 1 ], me[ 2 ] ).length();
- var scaleY = 1 / v1.set( me[ 4 ], me[ 5 ], me[ 6 ] ).length();
- var scaleZ = 1 / v1.set( me[ 8 ], me[ 9 ], me[ 10 ] ).length();
- te[ 0 ] = me[ 0 ] * scaleX;
- te[ 1 ] = me[ 1 ] * scaleX;
- te[ 2 ] = me[ 2 ] * scaleX;
- te[ 4 ] = me[ 4 ] * scaleY;
- te[ 5 ] = me[ 5 ] * scaleY;
- te[ 6 ] = me[ 6 ] * scaleY;
- te[ 8 ] = me[ 8 ] * scaleZ;
- te[ 9 ] = me[ 9 ] * scaleZ;
- te[ 10 ] = me[ 10 ] * scaleZ;
- return this;
- };
- }() */
- }
- OIMO.Mat33 = function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- this.elements = new OIMO_ARRAY_TYPE(9);
- var te = this.elements;
- this.init(
- (e00 !== undefined) ? e00 : 1, e01 || 0, e02 || 0,
- e10 || 0, (e11 !== undefined) ? e11 : 1, e12 || 0,
- e20 || 0, e21 || 0, (e22 !== undefined) ? e22 : 1
- );
- };
- OIMO.Mat33.prototype = {
- constructor: OIMO.Mat33,
- set: function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- var te = this.elements;
- te[0] = e00; te[1] = e01; te[2] = e02;
- te[3] = e10; te[4] = e11; te[5] = e12;
- te[6] = e20; te[7] = e21; te[8] = e22;
- return this;
- },
- init: function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- var te = this.elements;
- te[0] = e00; te[1] = e01; te[2] = e02;
- te[3] = e10; te[4] = e11; te[5] = e12;
- te[6] = e20; te[7] = e21; te[8] = e22;
- return this;
- },
- multiply: function (s) {
- var te = this.elements;
- te[0] *= s; te[1] *= s; te[2] *= s;
- te[3] *= s; te[4] *= s; te[5] *= s;
- te[6] *= s; te[7] *= s; te[8] *= s;
- return this;
- },
- add: function (m1, m2) {
- var te = this.elements, tem1 = m1.elements, tem2 = m2.elements;
- te[0] = tem1[0] + tem2[0]; te[1] = tem1[1] + tem2[1]; te[2] = tem1[2] + tem2[2];
- te[3] = tem1[3] + tem2[3]; te[4] = tem1[4] + tem2[4]; te[5] = tem1[5] + tem2[5];
- te[6] = tem1[6] + tem2[6]; te[7] = tem1[7] + tem2[7]; te[8] = tem1[8] + tem2[8];
- return this;
- },
- addEqual: function (m) {
- var te = this.elements, tem = m.elements;
- te[0] += tem[0]; te[1] += tem[1]; te[2] += tem[2];
- te[3] += tem[3]; te[4] += tem[4]; te[5] += tem[5];
- te[6] += tem[6]; te[7] += tem[7]; te[8] += tem[8];
- return this;
- },
- sub: function (m1, m2) {
- var te = this.elements, tem1 = m1.elements, tem2 = m2.elements;
- te[0] = tem1[0] - tem2[0]; te[1] = tem1[1] - tem2[1]; te[2] = tem1[2] - tem2[2];
- te[3] = tem1[3] - tem2[3]; te[4] = tem1[4] - tem2[4]; te[5] = tem1[5] - tem2[5];
- te[6] = tem1[6] - tem2[6]; te[7] = tem1[7] - tem2[7]; te[8] = tem1[8] - tem2[8];
- return this;
- },
- subEqual: function (m) {
- var te = this.elements, tem = m.elements;
- te[0] -= tem[0]; te[1] -= tem[1]; te[2] -= tem[2];
- te[3] -= tem[3]; te[4] -= tem[4]; te[5] -= tem[5];
- te[6] -= tem[6]; te[7] -= tem[7]; te[8] -= tem[8];
- return this;
- },
- scale: function (m, s) {
- var te = this.elements, tm = m.elements;
- te[0] = tm[0] * s; te[1] = tm[1] * s; te[2] = tm[2] * s;
- te[3] = tm[3] * s; te[4] = tm[4] * s; te[5] = tm[5] * s;
- te[6] = tm[6] * s; te[7] = tm[7] * s; te[8] = tm[8] * s;
- return this;
- },
- scaleEqual: function (s) {
- var te = this.elements;
- te[0] *= s; te[1] *= s; te[2] *= s;
- te[3] *= s; te[4] *= s; te[5] *= s;
- te[6] *= s; te[7] *= s; te[8] *= s;
- return this;
- },
- mul: function (m1, m2) {
- var te = this.elements, tm1 = m1.elements, tm2 = m2.elements,
- a0 = tm1[0], a3 = tm1[3], a6 = tm1[6],
- a1 = tm1[1], a4 = tm1[4], a7 = tm1[7],
- a2 = tm1[2], a5 = tm1[5], a8 = tm1[8],
- b0 = tm2[0], b3 = tm2[3], b6 = tm2[6],
- b1 = tm2[1], b4 = tm2[4], b7 = tm2[7],
- b2 = tm2[2], b5 = tm2[5], b8 = tm2[8];
- te[0] = a0 * b0 + a1 * b3 + a2 * b6;
- te[1] = a0 * b1 + a1 * b4 + a2 * b7;
- te[2] = a0 * b2 + a1 * b5 + a2 * b8;
- te[3] = a3 * b0 + a4 * b3 + a5 * b6;
- te[4] = a3 * b1 + a4 * b4 + a5 * b7;
- te[5] = a3 * b2 + a4 * b5 + a5 * b8;
- te[6] = a6 * b0 + a7 * b3 + a8 * b6;
- te[7] = a6 * b1 + a7 * b4 + a8 * b7;
- te[8] = a6 * b2 + a7 * b5 + a8 * b8;
- return this;
- },
- mulScale: function (m, sx, sy, sz, Prepend) {
- var prepend = Prepend || false;
- var te = this.elements, tm = m.elements;
- if (prepend) {
- te[0] = sx * tm[0]; te[1] = sx * tm[1]; te[2] = sx * tm[2];
- te[3] = sy * tm[3]; te[4] = sy * tm[4]; te[5] = sy * tm[5];
- te[6] = sz * tm[6]; te[7] = sz * tm[7]; te[8] = sz * tm[8];
- } else {
- te[0] = tm[0] * sx; te[1] = tm[1] * sy; te[2] = tm[2] * sz;
- te[3] = tm[3] * sx; te[4] = tm[4] * sy; te[5] = tm[5] * sz;
- te[6] = tm[6] * sx; te[7] = tm[7] * sy; te[8] = tm[8] * sz;
- }
- return this;
- },
- mulRotate: function (m, rad, ax, ay, az, Prepend) {
- var prepend = Prepend || false;
- var s = OIMO.sin(rad);
- var c = OIMO.cos(rad);
- var c1 = 1 - c;
- var r00 = ax * ax * c1 + c;
- var r01 = ax * ay * c1 - az * s;
- var r02 = ax * az * c1 + ay * s;
- var r10 = ay * ax * c1 + az * s;
- var r11 = ay * ay * c1 + c;
- var r12 = ay * az * c1 - ax * s;
- var r20 = az * ax * c1 - ay * s;
- var r21 = az * ay * c1 + ax * s;
- var r22 = az * az * c1 + c;
- var tm = m.elements;
- var a0 = tm[0], a3 = tm[3], a6 = tm[6];
- var a1 = tm[1], a4 = tm[4], a7 = tm[7];
- var a2 = tm[2], a5 = tm[5], a8 = tm[8];
- var te = this.elements;
- if (prepend) {
- te[0] = r00 * a0 + r01 * a3 + r02 * a6;
- te[1] = r00 * a1 + r01 * a4 + r02 * a7;
- te[2] = r00 * a2 + r01 * a5 + r02 * a8;
- te[3] = r10 * a0 + r11 * a3 + r12 * a6;
- te[4] = r10 * a1 + r11 * a4 + r12 * a7;
- te[5] = r10 * a2 + r11 * a5 + r12 * a8;
- te[6] = r20 * a0 + r21 * a3 + r22 * a6;
- te[7] = r20 * a1 + r21 * a4 + r22 * a7;
- te[8] = r20 * a2 + r21 * a5 + r22 * a8;
- } else {
- te[0] = a0 * r00 + a1 * r10 + a2 * r20;
- te[1] = a0 * r01 + a1 * r11 + a2 * r21;
- te[2] = a0 * r02 + a1 * r12 + a2 * r22;
- te[3] = a3 * r00 + a4 * r10 + a5 * r20;
- te[4] = a3 * r01 + a4 * r11 + a5 * r21;
- te[5] = a3 * r02 + a4 * r12 + a5 * r22;
- te[6] = a6 * r00 + a7 * r10 + a8 * r20;
- te[7] = a6 * r01 + a7 * r11 + a8 * r21;
- te[8] = a6 * r02 + a7 * r12 + a8 * r22;
- }
- return this;
- },
- transpose: function (m) {
- var te = this.elements, tm = m.elements;
- te[0] = tm[0]; te[1] = tm[3]; te[2] = tm[6];
- te[3] = tm[1]; te[4] = tm[4]; te[5] = tm[7];
- te[6] = tm[2]; te[7] = tm[5]; te[8] = tm[8];
- return this;
- },
- setQuat: function (q) {
- var te = this.elements,
- x2 = 2 * q.x, y2 = 2 * q.y, z2 = 2 * q.z,
- xx = q.x * x2, yy = q.y * y2, zz = q.z * z2,
- xy = q.x * y2, yz = q.y * z2, xz = q.x * z2,
- sx = q.s * x2, sy = q.s * y2, sz = q.s * z2;
- te[0] = 1 - yy - zz;
- te[1] = xy - sz;
- te[2] = xz + sy;
- te[3] = xy + sz;
- te[4] = 1 - xx - zz;
- te[5] = yz - sx;
- te[6] = xz - sy;
- te[7] = yz + sx;
- te[8] = 1 - xx - yy;
- return this;
- },
- invert: function (m) {
- var te = this.elements, tm = m.elements,
- a0 = tm[0], a3 = tm[3], a6 = tm[6],
- a1 = tm[1], a4 = tm[4], a7 = tm[7],
- a2 = tm[2], a5 = tm[5], a8 = tm[8],
- b01 = a4 * a8 - a7 * a5,
- b11 = a7 * a2 - a1 * a8,
- b21 = a1 * a5 - a4 * a2,
- dt = a0 * (b01) + a3 * (b11) + a6 * (b21);
- if (dt != 0) { dt = 1.0 / dt; }
- te[0] = dt * b01;//(a4*a8 - a5*a7);
- te[1] = dt * b11;//(a2*a7 - a1*a8);
- te[2] = dt * b21;//(a1*a5 - a2*a4);
- te[3] = dt * (a5 * a6 - a3 * a8);
- te[4] = dt * (a0 * a8 - a2 * a6);
- te[5] = dt * (a2 * a3 - a0 * a5);
- te[6] = dt * (a3 * a7 - a4 * a6);
- te[7] = dt * (a1 * a6 - a0 * a7);
- te[8] = dt * (a0 * a4 - a1 * a3);
- return this;
- },
- /*copy: function(m){
- var te = this.elements, tem = m.elements;
- te[0] = tem[0]; te[1] = tem[1]; te[2] = tem[2];
- te[3] = tem[3]; te[4] = tem[4]; te[5] = tem[5];
- te[6] = tem[6]; te[7] = tem[7]; te[8] = tem[8];
- return this;
- },*/
- toEuler: function () { // not work !!
- function clamp(x) {
- return OIMO.min(OIMO.max(x, -1), 1);
- }
- var te = this.elements;
- var m11 = te[0], m12 = te[3], m13 = te[6];
- var m21 = te[1], m22 = te[4], m23 = te[7];
- var m31 = te[2], m32 = te[5], m33 = te[8];
- var p = new OIMO.Vec3();
- var d = new OIMO.Quat();
- var s;
- p.y = OIMO.asin(clamp(m13));
- if (OIMO.abs(m13) < 0.99999) {
- p.x = OIMO.atan2(-m23, m33);
- p.z = OIMO.atan2(-m12, m11);
- } else {
- p.x = OIMO.atan2(m32, m22);
- p.z = 0;
- }
- return p;
- },
- /*clone: function(){
- var te = this.elements;
- return new OIMO.Mat33(
- te[0], te[1], te[2],
- te[3], te[4], te[5],
- te[6], te[7], te[8]
- );
- },*/
- toString: function () {
- var te = this.elements;
- var text =
- "Mat33|" + te[0].toFixed(4) + ", " + te[1].toFixed(4) + ", " + te[2].toFixed(4) + "|\n" +
- " |" + te[3].toFixed(4) + ", " + te[4].toFixed(4) + ", " + te[5].toFixed(4) + "|\n" +
- " |" + te[6].toFixed(4) + ", " + te[7].toFixed(4) + ", " + te[8].toFixed(4) + "|";
- return text;
- },
- // OK
- multiplyScalar: function (s) {
- var te = this.elements;
- te[0] *= s; te[3] *= s; te[6] *= s;
- te[1] *= s; te[4] *= s; te[7] *= s;
- te[2] *= s; te[5] *= s; te[8] *= s;
- return this;
- },
- identity: function () {
- this.set(1, 0, 0, 0, 1, 0, 0, 0, 1);
- return this;
- },
- clone: function () {
- return new this.constructor().fromArray(this.elements);
- },
- copy: function (m) {
- var me = m.elements;
- this.set(
- me[0], me[3], me[6],
- me[1], me[4], me[7],
- me[2], me[5], me[8]
- );
- return this;
- },
- fromArray: function (array) {
- this.elements.set(array);
- return this;
- },
- toArray: function () {
- var te = this.elements;
- return [
- te[0], te[1], te[2],
- te[3], te[4], te[5],
- te[6], te[7], te[8]
- ];
- }
- };
- OIMO.Quat = function (s, x, y, z) {
- this.s = (s !== undefined) ? s : 1;
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- };
- OIMO.Quat.prototype = {
- constructor: OIMO.Quat,
- set: function (x, y, z, w) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.s = w;
- return this;
- },
- init: function (s, x, y, z) {
- this.s = (s !== undefined) ? s : 1;
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- return this;
- },
- add: function (q1, q2) {
- this.s = q1.s + q2.s;
- this.x = q1.x + q2.x;
- this.y = q1.y + q2.y;
- this.z = q1.z + q2.z;
- return this;
- },
- addTime: function (v, t) {
- var x = v.x;
- var y = v.y;
- var z = v.z;
- var qs = this.s;
- var qx = this.x;
- var qy = this.y;
- var qz = this.z;
- t *= 0.5;
- var ns = (-x * qx - y * qy - z * qz) * t;
- var nx = (x * qs + y * qz - z * qy) * t;
- var ny = (-x * qz + y * qs + z * qx) * t;
- var nz = (x * qy - y * qx + z * qs) * t;
- qs += ns;
- qx += nx;
- qy += ny;
- qz += nz;
- var s = 1 / OIMO.sqrt(qs * qs + qx * qx + qy * qy + qz * qz);
- this.s = qs * s;
- this.x = qx * s;
- this.y = qy * s;
- this.z = qz * s;
- return this;
- },
- sub: function (q1, q2) {
- this.s = q1.s - q2.s;
- this.x = q1.x - q2.x;
- this.y = q1.y - q2.y;
- this.z = q1.z - q2.z;
- return this;
- },
- scale: function (q, s) {
- this.s = q.s * s;
- this.x = q.x * s;
- this.y = q.y * s;
- this.z = q.z * s;
- return this;
- },
- mul: function (q1, q2) {
- var ax = q1.x, ay = q1.y, az = q1.z, as = q1.s,
- bx = q2.x, by = q2.y, bz = q2.z, bs = q2.s;
- this.x = ax * bs + as * bx + ay * bz - az * by;
- this.y = ay * bs + as * by + az * bx - ax * bz;
- this.z = az * bs + as * bz + ax * by - ay * bx;
- this.s = as * bs - ax * bx - ay * by - az * bz;
- return this;
- },
- arc: function (v1, v2) {
- var x1 = v1.x;
- var y1 = v1.y;
- var z1 = v1.z;
- var x2 = v2.x;
- var y2 = v2.y;
- var z2 = v2.z;
- var d = x1 * x2 + y1 * y2 + z1 * z2;
- if (d == -1) {
- x2 = y1 * x1 - z1 * z1;
- y2 = -z1 * y1 - x1 * x1;
- z2 = x1 * z1 + y1 * y1;
- d = 1 / OIMO.sqrt(x2 * x2 + y2 * y2 + z2 * z2);
- this.s = 0;
- this.x = x2 * d;
- this.y = y2 * d;
- this.z = z2 * d;
- return this;
- }
- var cx = y1 * z2 - z1 * y2;
- var cy = z1 * x2 - x1 * z2;
- var cz = x1 * y2 - y1 * x2;
- this.s = OIMO.sqrt((1 + d) * 0.5);
- d = 0.5 / this.s;
- this.x = cx * d;
- this.y = cy * d;
- this.z = cz * d;
- return this;
- },
- normalize: function (q) {
- var len = OIMO.sqrt(q.s * q.s + q.x * q.x + q.y * q.y + q.z * q.z);
- if (len > 0) { len = 1 / len; }
- this.s = q.s * len;
- this.x = q.x * len;
- this.y = q.y * len;
- this.z = q.z * len;
- return this;
- },
- invert: function (q) {
- this.s = q.s;
- this.x = -q.x;
- this.y = -q.y;
- this.z = -q.z;
- return this;
- },
- length: function () {
- return OIMO.sqrt(this.s * this.s + this.x * this.x + this.y * this.y + this.z * this.z);
- },
- copy: function (q) {
- this.s = q.s;
- this.x = q.x;
- this.y = q.y;
- this.z = q.z;
- return this;
- },
- testDiff: function (q) {
- if (this.s !== q.s || this.x !== q.x || this.y !== q.y || this.z !== q.z) return true;
- else return false;
- },
- clone: function (q) {
- return new OIMO.Quat(this.s, this.x, this.y, this.z);
- },
- toString: function () {
- return "Quat[" + this.s.toFixed(4) + ", (" + this.x.toFixed(4) + ", " + this.y.toFixed(4) + ", " + this.z.toFixed(4) + ")]";
- }
- }
- // for three easy export
- OIMO.Quaternion = function (x, y, z, w) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.w = (w !== undefined) ? w : 1;
- };
- OIMO.Quaternion.prototype = {
- constructor: OIMO.Quaternion,
- setFromRotationMatrix: function (m) {
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- var te = m.elements,
- m11 = te[0], m12 = te[1], m13 = te[2],
- m21 = te[3], m22 = te[4], m23 = te[5],
- m31 = te[6], m32 = te[7], m33 = te[8],
- trace = m11 + m22 + m33,
- s;
- if (trace > 0) {
- s = 0.5 / OIMO.sqrt(trace + 1.0);
- this.w = 0.25 / s;
- this.x = (m32 - m23) * s;
- this.y = (m13 - m31) * s;
- this.z = (m21 - m12) * s;
- } else if (m11 > m22 && m11 > m33) {
- s = 2.0 * OIMO.sqrt(1.0 + m11 - m22 - m33);
- this.w = (m32 - m23) / s;
- this.x = 0.25 * s;
- this.y = (m12 + m21) / s;
- this.z = (m13 + m31) / s;
- } else if (m22 > m33) {
- s = 2.0 * OIMO.sqrt(1.0 + m22 - m11 - m33);
- this.w = (m13 - m31) / s;
- this.x = (m12 + m21) / s;
- this.y = 0.25 * s;
- this.z = (m23 + m32) / s;
- } else {
- s = 2.0 * OIMO.sqrt(1.0 + m33 - m11 - m22);
- this.w = (m21 - m12) / s;
- this.x = (m13 + m31) / s;
- this.y = (m23 + m32) / s;
- this.z = 0.25 * s;
- }
- //this.onChangeCallback();
- return this;
- }
- }
- OIMO.Vec3 = function (x, y, z) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- };
- OIMO.Vec3.prototype = {
- constructor: OIMO.Vec3,
- init: function (x, y, z) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- return this;
- },
- set: function (x, y, z) {
- this.x = x;
- this.y = y;
- this.z = z;
- return this;
- },
- add: function (v1, v2) {
- this.x = v1.x + v2.x;
- this.y = v1.y + v2.y;
- this.z = v1.z + v2.z;
- return this;
- },
- addEqual: function (v) {
- this.x += v.x;
- this.y += v.y;
- this.z += v.z;
- return this;
- },
- addTime: function (v, t) {
- this.x += v.x * t;
- this.y += v.y * t;
- this.z += v.z * t;
- return this;
- },
- sub: function (v1, v2) {
- this.x = v1.x - v2.x;
- this.y = v1.y - v2.y;
- this.z = v1.z - v2.z;
- return this;
- },
- subEqual: function (v) {
- this.x -= v.x;
- this.y -= v.y;
- this.z -= v.z;
- return this;
- },
- addScale: function (v, s) {
- this.x += v.x * s;
- this.y += v.y * s;
- this.z += v.z * s;
- return this;
- },
- scale: function (v, s) {
- this.x = v.x * s;
- this.y = v.y * s;
- this.z = v.z * s;
- return this;
- },
- scaleEqual: function (s) {
- this.x *= s;
- this.y *= s;
- this.z *= s;
- return this;
- },
- /*dot: function(v){
- return this.x*v.x+this.y*v.y+this.z*v.z;
- },*/
- cross: function (v1, v2) {
- var ax = v1.x, ay = v1.y, az = v1.z,
- bx = v2.x, by = v2.y, bz = v2.z;
- this.x = ay * bz - az * by;
- this.y = az * bx - ax * bz;
- this.z = ax * by - ay * bx;
- return this;
- },
- mul: function (o, v, m) {
- var te = m.elements;
- this.x = o.x + v.x * te[0] + v.y * te[1] + v.z * te[2];
- this.y = o.y + v.x * te[3] + v.y * te[4] + v.z * te[5];
- this.z = o.z + v.x * te[6] + v.y * te[7] + v.z * te[8];
- return this;
- },
- mulMat: function (m, v) {
- var te = m.elements;
- this.x = te[0] * v.x + te[1] * v.y + te[2] * v.z;
- this.y = te[3] * v.x + te[4] * v.y + te[5] * v.z;
- this.z = te[6] * v.x + te[7] * v.y + te[8] * v.z;
- return this;
- },
- normalize: function (v) {
- var x = v.x, y = v.y, z = v.z;
- var l = x * x + y * y + z * z;
- if (l > 0) {
- l = 1 / OIMO.sqrt(l);
- this.x = x * l;
- this.y = y * l;
- this.z = z * l;
- }
- return this;
- },
- /*norm: function(){
- var x = this.x, y = this.y, z = this.z;
- var l = x*x + y*y + z*z;
- if (l > 0) {
- l = 1 / OIMO.sqrt(l);
- this.x = x*l;
- this.y = y*l;
- this.z = z*l;
- }
- return this;
- },*/
- invert: function (v) {
- this.x = -v.x;
- this.y = -v.y;
- this.z = -v.z;
- return this;
- },
- /*length: function(){
- var x = this.x, y = this.y, z = this.z;
- return OIMO.sqrt(x*x + y*y + z*z);
- },*/
- negate: function () {
- this.x = -this.x;
- this.y = -this.y;
- this.z = -this.z;
- return this;
- },
- dot: function (v) {
- return this.x * v.x + this.y * v.y + this.z * v.z;
- },
- lengthSq: function () {
- return this.x * this.x + this.y * this.y + this.z * this.z;
- },
- length: function () {
- return OIMO.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
- },
- /*len: function(){
- var x = this.x, y = this.y, z = this.z;
- return x*x + y*y + z*z;
- },*/
- copy: function (v) {
- this.x = v.x;
- this.y = v.y;
- this.z = v.z;
- return this;
- },
- applyQuaternion: function (q) {
- var x = this.x;
- var y = this.y;
- var z = this.z;
- var qx = q.x;
- var qy = q.y;
- var qz = q.z;
- var qs = q.s;
- // calculate quat * vector
- var ix = qs * x + qy * z - qz * y;
- var iy = qs * y + qz * x - qx * z;
- var iz = qs * z + qx * y - qy * x;
- var iw = -qx * x - qy * y - qz * z;
- // calculate result * inverse quat
- this.x = ix * qs + iw * -qx + iy * -qz - iz * -qy;
- this.y = iy * qs + iw * -qy + iz * -qx - ix * -qz;
- this.z = iz * qs + iw * -qz + ix * -qy - iy * -qx;
- return this;
- },
- testZero: function () {
- if (this.x !== 0 || this.y !== 0 || this.z !== 0) return true;
- else return false;
- },
- testDiff: function (v) {
- return ((v.x !== this.x) || (v.y !== this.y) || (v.z !== this.z));
- //if(this.x!==v.x || this.y!==v.y || this.z!==v.z) return true;
- //else return false;
- },
- equals: function (v) {
- return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
- },
- clone: function () {
- return new this.constructor(this.x, this.y, this.z);
- },
- toString: function () {
- return "Vec3[" + this.x.toFixed(4) + ", " + this.y.toFixed(4) + ", " + this.z.toFixed(4) + "]";
- },
- multiplyScalar: function (scalar) {
- if (isFinite(scalar)) {
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
- } else {
- this.x = 0;
- this.y = 0;
- this.z = 0;
- }
- return this;
- },
- divideScalar: function (scalar) {
- return this.multiplyScalar(1 / scalar);
- },
- // TODO rename to normalize
- norm: function () {
- return this.divideScalar(this.length());
- },
- }
- OIMO.Euler = function (x, y, z, order) {
- this._x = x || 0;
- this._y = y || 0;
- this._z = z || 0;
- this._order = order || OIMO.Euler.DefaultOrder;
- };
- OIMO.Euler.RotationOrders = ['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX'];
- OIMO.Euler.DefaultOrder = 'XYZ';
- OIMO.clamp = function (x, a, b) {
- return (x < a) ? a : ((x > b) ? b : x);
- }
- OIMO.Euler.prototype = {
- constructor: OIMO.Euler,
- _x: 0, _y: 0, _z: 0, _order: OIMO.Euler.DefaultOrder,
- get x() {
- return this._x;
- },
- set x(value) {
- this._x = value;
- this.onChangeCallback();
- },
- get y() {
- return this._y;
- },
- set y(value) {
- this._y = value;
- this.onChangeCallback();
- },
- get z() {
- return this._z;
- },
- set z(value) {
- this._z = value;
- this.onChangeCallback();
- },
- get order() {
- return this._order;
- },
- set order(value) {
- this._order = value;
- this.onChangeCallback();
- },
- set: function (x, y, z, order) {
- this._x = x;
- this._y = y;
- this._z = z;
- this._order = order || this._order;
- this.onChangeCallback();
- return this;
- },
- copy: function (euler) {
- this._x = euler._x;
- this._y = euler._y;
- this._z = euler._z;
- this._order = euler._order;
- this.onChangeCallback();
- return this;
- },
- setFromRotationMatrix: function (m, order) {
- var clamp = OIMO.clamp;
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- var te = m.elements;
- /*var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
- var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
- var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];*/
- var m11 = te[0], m12 = te[1], m13 = te[2],
- m21 = te[3], m22 = te[4], m23 = te[5],
- m31 = te[6], m32 = te[7], m33 = te[8];
- order = order || this._order;
- if (order === 'XYZ') {
- this._y = OIMO.asin(clamp(m13, -1, 1));
- if (OIMO.abs(m13) < 0.99999) {
- this._x = OIMO.atan2(-m23, m33);
- this._z = OIMO.atan2(-m12, m11);
- } else {
- this._x = OIMO.atan2(m32, m22);
- this._z = 0;
- }
- } else if (order === 'YXZ') {
- this._x = OIMO.asin(-clamp(m23, -1, 1));
- if (OIMO.abs(m23) < 0.99999) {
- this._y = OIMO.atan2(m13, m33);
- this._z = OIMO.atan2(m21, m22);
- } else {
- this._y = OIMO.atan2(-m31, m11);
- this._z = 0;
- }
- } else if (order === 'ZXY') {
- this._x = OIMO.asin(clamp(m32, -1, 1));
- if (OIMO.abs(m32) < 0.99999) {
- this._y = OIMO.atan2(-m31, m33);
- this._z = OIMO.atan2(-m12, m22);
- } else {
- this._y = 0;
- this._z = OIMO.atan2(m21, m11);
- }
- } else if (order === 'ZYX') {
- this._y = OIMO.asin(-clamp(m31, -1, 1));
- if (OIMO.abs(m31) < 0.99999) {
- this._x = OIMO.atan2(m32, m33);
- this._z = OIMO.atan2(m21, m11);
- } else {
- this._x = 0;
- this._z = OIMO.atan2(-m12, m22);
- }
- } else if (order === 'YZX') {
- this._z = OIMO.asin(clamp(m21, -1, 1));
- if (OIMO.abs(m21) < 0.99999) {
- this._x = OIMO.atan2(-m23, m22);
- this._y = OIMO.atan2(-m31, m11);
- } else {
- this._x = 0;
- this._y = OIMO.atan2(m13, m33);
- }
- } else if (order === 'XZY') {
- this._z = OIMO.asin(-clamp(m12, -1, 1));
- if (OIMO.abs(m12) < 0.99999) {
- this._x = OIMO.atan2(m32, m22);
- this._y = OIMO.atan2(m13, m11);
- } else {
- this._x = OIMO.atan2(-m23, m33);
- this._y = 0;
- }
- } else {
- console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order)
- }
- this._order = order;
- this.onChangeCallback();
- return this;
- },
- setFromQuaternion: function (q, order, update) {
- var clamp = OIMO.clamp;
- // q is assumed to be normalized
- // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
- var sqx = q.x * q.x;
- var sqy = q.y * q.y;
- var sqz = q.z * q.z;
- var sqw = q.s * q.s;
- order = order || this._order;
- if (order === 'XYZ') {
- this._x = OIMO.atan2(2 * (q.x * q.s - q.y * q.z), (sqw - sqx - sqy + sqz));
- this._y = OIMO.asin(clamp(2 * (q.x * q.z + q.y * q.s), -1, 1));
- this._z = OIMO.atan2(2 * (q.z * q.s - q.x * q.y), (sqw + sqx - sqy - sqz));
- } else if (order === 'YXZ') {
- this._x = OIMO.asin(clamp(2 * (q.x * q.s - q.y * q.z), -1, 1));
- this._y = OIMO.atan2(2 * (q.x * q.z + q.y * q.s), (sqw - sqx - sqy + sqz));
- this._z = OIMO.atan2(2 * (q.x * q.y + q.z * q.s), (sqw - sqx + sqy - sqz));
- } else if (order === 'ZXY') {
- this._x = OIMO.asin(clamp(2 * (q.x * q.s + q.y * q.z), -1, 1));
- this._y = OIMO.atan2(2 * (q.y * q.s - q.z * q.x), (sqw - sqx - sqy + sqz));
- this._z = OIMO.atan2(2 * (q.z * q.s - q.x * q.y), (sqw - sqx + sqy - sqz));
- } else if (order === 'ZYX') {
- this._x = OIMO.atan2(2 * (q.x * q.s + q.z * q.y), (sqw - sqx - sqy + sqz));
- this._y = OIMO.asin(clamp(2 * (q.y * q.s - q.x * q.z), -1, 1));
- this._z = OIMO.atan2(2 * (q.x * q.y + q.z * q.s), (sqw + sqx - sqy - sqz));
- } else if (order === 'YZX') {
- this._x = OIMO.atan2(2 * (q.x * q.s - q.z * q.y), (sqw - sqx + sqy - sqz));
- this._y = OIMO.atan2(2 * (q.y * q.s - q.x * q.z), (sqw + sqx - sqy - sqz));
- this._z = OIMO.asin(clamp(2 * (q.x * q.y + q.z * q.s), -1, 1));
- } else if (order === 'XZY') {
- this._x = OIMO.atan2(2 * (q.x * q.s + q.y * q.z), (sqw - sqx + sqy - sqz));
- this._y = OIMO.atan2(2 * (q.x * q.z + q.y * q.s), (sqw + sqx - sqy - sqz));
- this._z = OIMO.asin(clamp(2 * (q.z * q.s - q.x * q.y), -1, 1));
- } else {
- console.warn('OIMO.Euler: .setFromQuaternion() given unsupported order: ' + order)
- }
- this._order = order;
- if (update !== false) this.onChangeCallback();
- return this;
- },
- reorder: function () {
- // WARNING: this discards revolution information -bhouston
- var q = new OIMO.Quat();
- return function (newOrder) {
- q.setFromEuler(this);
- this.setFromQuaternion(q, newOrder);
- };
- }(),
- equals: function (euler) {
- return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
- },
- fromArray: function (array) {
- this._x = array[0];
- this._y = array[1];
- this._z = array[2];
- if (array[3] !== undefined) this._order = array[3];
- this.onChangeCallback();
- return this;
- },
- toArray: function () {
- return [this._x, this._y, this._z, this._order];
- },
- onChange: function (callback) {
- this.onChangeCallback = callback;
- return this;
- },
- onChangeCallback: function () { },
- clone: function () {
- return new OIMO.Euler(this._x, this._y, this._z, this._order);
- }
- };
- OIMO.EulerToAxis = function (ox, oy, oz) {// angles in radians
- var c1 = OIMO.cos(oy * 0.5);//heading
- var s1 = OIMO.sin(oy * 0.5);
- var c2 = OIMO.cos(oz * 0.5);//altitude
- var s2 = OIMO.sin(oz * 0.5);
- var c3 = OIMO.cos(ox * 0.5);//bank
- var s3 = OIMO.sin(ox * 0.5);
- var c1c2 = c1 * c2;
- var s1s2 = s1 * s2;
- var w = c1c2 * c3 - s1s2 * s3;
- var x = c1c2 * s3 + s1s2 * c3;
- var y = s1 * c2 * c3 + c1 * s2 * s3;
- var z = c1 * s2 * c3 - s1 * c2 * s3;
- var angle = 2 * OIMO.acos(w);
- var norm = x * x + y * y + z * z;
- if (norm < 0.001) {
- x = 1;
- y = z = 0;
- } else {
- norm = OIMO.sqrt(norm);
- x /= norm;
- y /= norm;
- z /= norm;
- }
- return [angle, x, y, z];
- }
- OIMO.EulerToMatrix = function (ox, oy, oz) {// angles in radians
- var ch = OIMO.cos(oy);//heading
- var sh = OIMO.sin(oy);
- var ca = OIMO.cos(oz);//altitude
- var sa = OIMO.sin(oz);
- var cb = OIMO.cos(ox);//bank
- var sb = OIMO.sin(ox);
- var mtx = new OIMO.Mat33();
- var te = mtx.elements;
- te[0] = ch * ca;
- te[1] = sh * sb - ch * sa * cb;
- te[2] = ch * sa * sb + sh * cb;
- te[3] = sa;
- te[4] = ca * cb;
- te[5] = -ca * sb;
- te[6] = -sh * ca;
- te[7] = sh * sa * cb + ch * sb;
- te[8] = -sh * sa * sb + ch * cb;
- return mtx;
- }
- OIMO.MatrixToEuler = function (mtx) {// angles in radians
- var te = mtx.elements;
- var x, y, z;
- if (te[3] > 0.998) { // singularity at north pole
- y = OIMO.atan2(te[2], te[8]);
- z = OIMO.PI / 2;
- x = 0;
- } else if (te[3] < -0.998) { // singularity at south pole
- y = OIMO.atan2(te[2], te[8]);
- z = -OIMO.PI / 2;
- x = 0;
- } else {
- y = OIMO.atan2(-te[6], te[0]);
- x = OIMO.atan2(-te[5], te[4]);
- z = OIMO.asin(te[3]);
- }
- return [x, y, z];
- }
- OIMO.unwrapDegrees = function (r) {
- r = r % 360;
- if (r > 180) r -= 360;
- if (r < -180) r += 360;
- return r;
- }
- OIMO.unwrapRadian = function (r) {
- r = r % OIMO.TwoPI;
- if (r > OIMO.PI) r -= OIMO.TwoPI;
- if (r < -OIMO.PI) r += OIMO.TwoPI;
- return r;
- }
- OIMO.Distance3d = function (p1, p2) {
- var xd = p2[0] - p1[0];
- var yd = p2[1] - p1[1];
- var zd = p2[2] - p1[2];
- return OIMO.sqrt(xd * xd + yd * yd + zd * zd);
- }
- /**
- * The base class of all type of the constraints.
- * @author saharan
- */
- OIMO.Constraint = function () {
- // The parent world of the constraint.
- this.parent = null;
- // The first body of the constraint.
- this.body1 = null;
- // The second body of the constraint.
- this.body2 = null;
- // Internal
- this.addedToIsland = false;
- }
- OIMO.Constraint.prototype = {
- constructor: OIMO.Constraint,
- /**
- * Prepare for solving the constraint.
- * @param timeStep
- * @param invTimeStep
- */
- preSolve: function (timeStep, invTimeStep) {
- OIMO.Error("Constraint", "Inheritance error.");
- },
- /**
- * Solve the constraint.
- * This is usually called iteratively.
- */
- solve: function () {
- OIMO.Error("Constraint", "Inheritance error.");
- },
- /**
- * Do the post-processing.
- */
- postSolve: function () {
- OIMO.Error("Constraint", "Inheritance error.");
- }
- }
- /**
- * Joints are used to constrain the motion between two rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.Joint = function (config) {
- OIMO.Constraint.call(this);
- // joint name
- this.name = "";
- // The type of the joint.
- this.type = OIMO.JOINT_NULL;
- // The previous joint in the world.
- this.prev = null;
- // The next joint in the world.
- this.next = null;
- this.body1 = config.body1;
- this.body2 = config.body2;
- // The anchor point on the first rigid body in local coordinate system.
- this.localAnchorPoint1 = new OIMO.Vec3().copy(config.localAnchorPoint1);
- // The anchor point on the second rigid body in local coordinate system.
- this.localAnchorPoint2 = new OIMO.Vec3().copy(config.localAnchorPoint2);
- // The anchor point on the first rigid body in world coordinate system relative to the body's origin.
- this.relativeAnchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in world coordinate system relative to the body's origin.
- this.relativeAnchorPoint2 = new OIMO.Vec3();
- // The anchor point on the first rigid body in world coordinate system.
- this.anchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in world coordinate system.
- this.anchorPoint2 = new OIMO.Vec3();
- // Whether allow collision between connected rigid bodies or not.
- this.allowCollision = config.allowCollision;
- this.b1Link = new OIMO.JointLink(this);
- this.b2Link = new OIMO.JointLink(this);
- this.matrix = new OIMO.Mat44();
- };
- OIMO.Joint.prototype = Object.create(OIMO.Constraint.prototype);
- OIMO.Joint.prototype.constructor = OIMO.Joint;
- // Update all the anchor points.
- OIMO.Joint.prototype.updateAnchorPoints = function () {
- this.relativeAnchorPoint1.mulMat(this.body1.rotation, this.localAnchorPoint1);
- this.relativeAnchorPoint2.mulMat(this.body2.rotation, this.localAnchorPoint2);
- this.anchorPoint1.add(this.relativeAnchorPoint1, this.body1.position);
- this.anchorPoint2.add(this.relativeAnchorPoint2, this.body2.position);
- };
- // Attach the joint from the bodies.
- OIMO.Joint.prototype.attach = function () {
- this.b1Link.body = this.body2;
- this.b2Link.body = this.body1;
- if (this.body1.jointLink != null) (this.b1Link.next = this.body1.jointLink).prev = this.b1Link;
- else this.b1Link.next = null;
- this.body1.jointLink = this.b1Link;
- this.body1.numJoints++;
- if (this.body2.jointLink != null) (this.b2Link.next = this.body2.jointLink).prev = this.b2Link;
- else this.b2Link.next = null;
- this.body2.jointLink = this.b2Link;
- this.body2.numJoints++;
- };
- // Detach the joint from the bodies.
- OIMO.Joint.prototype.detach = function () {
- var prev = this.b1Link.prev;
- var next = this.b1Link.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.body1.jointLink == this.b1Link) this.body1.jointLink = next;
- this.b1Link.prev = null;
- this.b1Link.next = null;
- this.b1Link.body = null;
- this.body1.numJoints--;
- prev = this.b2Link.prev;
- next = this.b2Link.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.body2.jointLink == this.b2Link) this.body2.jointLink = next;
- this.b2Link.prev = null;
- this.b2Link.next = null;
- this.b2Link.body = null;
- this.body2.numJoints--;
- this.b1Link.body = null;
- this.b2Link.body = null;
- };
- // Awake the bodies.
- OIMO.Joint.prototype.awake = function () {
- this.body1.awake();
- this.body2.awake();
- };
- // calculation function
- OIMO.Joint.prototype.preSolve = function (timeStep, invTimeStep) {
- };
- OIMO.Joint.prototype.solve = function () {
- };
- OIMO.Joint.prototype.postSolve = function () {
- };
- // Delete process
- OIMO.Joint.prototype.remove = function () {
- this.dispose();
- };
- OIMO.Joint.prototype.dispose = function () {
- this.parent.removeJoint(this);
- };
- // Three js add
- OIMO.Joint.prototype.getPosition = function () {
- var p1 = new OIMO.Vec3().scale(this.anchorPoint1, OIMO.WORLD_SCALE);
- var p2 = new OIMO.Vec3().scale(this.anchorPoint2, OIMO.WORLD_SCALE);
- return [p1, p2];
- };
- OIMO.Joint.prototype.getMatrix = function () {
- var m = this.matrix.elements;
- var p1 = this.anchorPoint1;
- var p2 = this.anchorPoint2;
- m[0] = p1.x * OIMO.WORLD_SCALE;
- m[1] = p1.y * OIMO.WORLD_SCALE;
- m[2] = p1.z * OIMO.WORLD_SCALE;
- m[3] = 0;
- m[4] = p2.x * OIMO.WORLD_SCALE;
- m[5] = p2.y * OIMO.WORLD_SCALE;
- m[6] = p2.z * OIMO.WORLD_SCALE;
- m[7] = 0;
- return m;
- };
- /**
- * A joint configuration holds all configuration data for constructing a joint.
- * Joint configurations can be reused safely.
- * @author saharan
- */
- OIMO.JointConfig = function () {
- // The first rigid body of the joint.
- this.body1 = null;
- // The second rigid body of the joint.
- this.body2 = null;
- // The anchor point on the first rigid body in local coordinate system.
- this.localAnchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in local coordinate system.
- this.localAnchorPoint2 = new OIMO.Vec3();
- // The axis in the first body's coordinate system.
- // his property is available in some joints.
- this.localAxis1 = new OIMO.Vec3();
- // The axis in the second body's coordinate system.
- // This property is available in some joints.
- this.localAxis2 = new OIMO.Vec3();
- // Whether allow collision between connected rigid bodies or not.
- this.allowCollision = false;
- };
- /**
- * A link list of joints.
- * @author saharan
- */
- OIMO.JointLink = function (joint) {
- // The previous joint link.
- this.prev = null;
- // The next joint link.
- this.next = null;
- // The other rigid body connected to the joint.
- this.body = null;
- // The joint of the link.
- this.joint = joint;
- };
- /**
- * An information of limit and motor.
- * @author saharan
- */
- OIMO.LimitMotor = function (axis, fixed) {
- fixed = fixed || false;
- // The axis of the constraint.
- this.axis = axis;
- // The current angle for rotational constraints.
- this.angle = 0;
- // The lower limit. Set lower > upper to disable
- this.lowerLimit = fixed ? 0 : 1;
- //if(fixed)this.lowerLimit = 0;
- //else this.lowerLimit = 1;
- // The upper limit. Set lower > upper to disable.
- this.upperLimit = 0;
- // The target motor speed.
- this.motorSpeed = 0;
- // The maximum motor force or torque. Set 0 to disable.
- this.maxMotorForce = 0;
- // The frequency of the spring. Set 0 to disable.
- this.frequency = 0;
- // The damping ratio of the spring. Set 0 for no damping, 1 for critical damping.
- this.dampingRatio = 0;
- };
- OIMO.LimitMotor.prototype = {
- constructor: OIMO.LimitMotor,
- /**
- * Set limit data into this constraint.
- * @param lowerLimit
- * @param upperLimit
- */
- setLimit: function (lowerLimit, upperLimit) {
- this.lowerLimit = lowerLimit;
- this.upperLimit = upperLimit;
- },
- /**
- * Set motor data into this constraint.
- * @param motorSpeed
- * @param maxMotorForce
- */
- setMotor: function (motorSpeed, maxMotorForce) {
- this.motorSpeed = motorSpeed;
- this.maxMotorForce = maxMotorForce;
- },
- /**
- * Set spring data into this constraint.
- * @param frequency
- * @param dampingRatio
- */
- setSpring: function (frequency, dampingRatio) {
- this.frequency = frequency;
- this.dampingRatio = dampingRatio;
- }
- };
- /**
- * A ball-and-socket joint limits relative translation on two anchor points on rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.BallAndSocketJoint = function (config) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_BALL_AND_SOCKET;
- this.lc = new OIMO.LinearConstraint(this);
- };
- OIMO.BallAndSocketJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.BallAndSocketJoint.prototype.constructor = OIMO.BallAndSocketJoint;
- OIMO.BallAndSocketJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.updateAnchorPoints();
- this.lc.preSolve(timeStep, invTimeStep);
- };
- OIMO.BallAndSocketJoint.prototype.solve = function () {
- this.lc.solve();
- };
- OIMO.BallAndSocketJoint.prototype.postSolve = function () {
- };
- /**
- * A distance joint limits the distance between two anchor points on rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.DistanceJoint = function (config, minDistance, maxDistance) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_DISTANCE;
- this.normal = new OIMO.Vec3();
- this.nr = new OIMO.Vec3();
- // The limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.normal, true);
- this.limitMotor.lowerLimit = minDistance;
- this.limitMotor.upperLimit = maxDistance;
- this.t = new OIMO.TranslationalConstraint(this, this.limitMotor);
- };
- OIMO.DistanceJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.DistanceJoint.prototype.constructor = OIMO.DistanceJoint;
- OIMO.DistanceJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.updateAnchorPoints();
- //var nr = this.nr;
- this.nr.sub(this.anchorPoint2, this.anchorPoint1);
- //var len = OIMO.sqrt( nr.x*nr.x + nr.y*nr.y + nr.z*nr.z );
- //if(len>0) len = 1/len;
- //this.normal.scale( nr, len );
- this.normal.normalize(this.nr);
- this.t.preSolve(timeStep, invTimeStep);
- };
- OIMO.DistanceJoint.prototype.solve = function () {
- this.t.solve();
- };
- OIMO.DistanceJoint.prototype.postSolve = function () {
- };
- /**
- * A hinge joint allows only for relative rotation of rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.HingeJoint = function (config, lowerAngleLimit, upperAngleLimit) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_HINGE;
- // The axis in the first body's coordinate system.
- this.localAxis1 = config.localAxis1.clone().norm();
- // The axis in the second body's coordinate system.
- this.localAxis2 = config.localAxis2.clone().norm();
- // make angle axis 1
- this.localAngle1 = new OIMO.Vec3(
- this.localAxis1.y * this.localAxis1.x - this.localAxis1.z * this.localAxis1.z,
- -this.localAxis1.z * this.localAxis1.y - this.localAxis1.x * this.localAxis1.x,
- this.localAxis1.x * this.localAxis1.z + this.localAxis1.y * this.localAxis1.y
- ).norm();
- // make angle axis 2
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- this.localAngle2 = new OIMO.Vec3().mulMat(arc, this.localAngle1);
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- this.ax1 = new OIMO.Vec3();
- this.ax2 = new OIMO.Vec3();
- this.an1 = new OIMO.Vec3();
- this.an2 = new OIMO.Vec3();
- // The rotational limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.nor, false);
- this.limitMotor.lowerLimit = lowerAngleLimit;
- this.limitMotor.upperLimit = upperAngleLimit;
- this.lc = new OIMO.LinearConstraint(this);
- this.r3 = new OIMO.Rotational3Constraint(this, this.limitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.HingeJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.HingeJoint.prototype.constructor = OIMO.HingeJoint;
- OIMO.HingeJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmp1X, tmp1Y, tmp1Z, limite;//, nx, ny, nz, tx, ty, tz, bx, by, bz;
- this.updateAnchorPoints();
- this.ax1.mulMat(this.body1.rotation, this.localAxis1);
- this.ax2.mulMat(this.body2.rotation, this.localAxis2);
- this.an1.mulMat(this.body1.rotation, this.localAngle1);
- this.an2.mulMat(this.body2.rotation, this.localAngle2);
- this.nor.set(
- this.ax1.x * this.body2.inverseMass + this.ax2.x * this.body1.inverseMass,
- this.ax1.y * this.body2.inverseMass + this.ax2.y * this.body1.inverseMass,
- this.ax1.z * this.body2.inverseMass + this.ax2.z * this.body1.inverseMass
- ).norm();
- this.tan.set(
- this.nor.y * this.nor.x - this.nor.z * this.nor.z,
- -this.nor.z * this.nor.y - this.nor.x * this.nor.x,
- this.nor.x * this.nor.z + this.nor.y * this.nor.y
- ).norm();
- this.bin.set(
- this.nor.y * this.tan.z - this.nor.z * this.tan.y,
- this.nor.z * this.tan.x - this.nor.x * this.tan.z,
- this.nor.x * this.tan.y - this.nor.y * this.tan.x
- );
- // calculate hinge angle
- limite = this.acosClamp(this.an1.x * this.an2.x + this.an1.y * this.an2.y + this.an1.z * this.an2.z)
- if (
- this.nor.x * (this.an1.y * this.an2.z - this.an1.z * this.an2.y) +
- this.nor.y * (this.an1.z * this.an2.x - this.an1.x * this.an2.z) +
- this.nor.z * (this.an1.x * this.an2.y - this.an1.y * this.an2.x) < 0
- ) {
- this.limitMotor.angle = -limite;
- } else {
- this.limitMotor.angle = limite;
- }
- tmp1X = this.ax1.y * this.ax2.z - this.ax1.z * this.ax2.y;
- tmp1Y = this.ax1.z * this.ax2.x - this.ax1.x * this.ax2.z;
- tmp1Z = this.ax1.x * this.ax2.y - this.ax1.y * this.ax2.x;
- this.r3.limitMotor2.angle = this.tan.x * tmp1X + this.tan.y * tmp1Y + this.tan.z * tmp1Z;
- this.r3.limitMotor3.angle = this.bin.x * tmp1X + this.bin.y * tmp1Y + this.bin.z * tmp1Z;
- this.r3.preSolve(timeStep, invTimeStep);
- this.lc.preSolve(timeStep, invTimeStep);
- };
- OIMO.HingeJoint.prototype.solve = function () {
- this.r3.solve();
- this.lc.solve();
- };
- OIMO.HingeJoint.prototype.postSolve = function () {
- };
- OIMO.HingeJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * A prismatic joint allows only for relative translation of rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.PrismaticJoint = function (config, lowerTranslation, upperTranslation) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_PRISMATIC;
- // The axis in the first body's coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The axis in the second body's coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- this.ac = new OIMO.AngularConstraint(this, new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- // The translational limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.nor, true);
- this.limitMotor.lowerLimit = lowerTranslation;
- this.limitMotor.upperLimit = upperTranslation;
- this.t3 = new OIMO.Translational3Constraint(this, this.limitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.PrismaticJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.PrismaticJoint.prototype.constructor = OIMO.PrismaticJoint;
- OIMO.PrismaticJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var axis1X = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var axis1Y = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var axis1Z = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var axis2X = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var axis2Y = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var axis2Z = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var nx = axis1X * this.body2.inverseMass + axis2X * this.body1.inverseMass;
- var ny = axis1Y * this.body2.inverseMass + axis2Y * this.body1.inverseMass;
- var nz = axis1Z * this.body2.inverseMass + axis2Z * this.body1.inverseMass;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * nx - nz * nz;
- var ty = -nz * ny - nx * nx;
- var tz = nx * nz + ny * ny;
- tmp1X = 1 / OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = ny * tz - nz * ty;
- var by = nz * tx - nx * tz;
- var bz = nx * ty - ny * tx;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- this.ac.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.PrismaticJoint.prototype.solve = function () {
- this.ac.solve();
- this.t3.solve();
- };
- OIMO.PrismaticJoint.prototype.postSolve = function () {
- };
- /**
- * A slider joint allows for relative translation and relative rotation between two rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.SliderJoint = function (config, lowerTranslation, upperTranslation) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_SLIDER;
- // The first axis in local coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The second axis in local coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- var len;
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAngAxis1X = this.localAxis1Y * this.localAxis1X - this.localAxis1Z * this.localAxis1Z;
- this.localAngAxis1Y = -this.localAxis1Z * this.localAxis1Y - this.localAxis1X * this.localAxis1X;
- this.localAngAxis1Z = this.localAxis1X * this.localAxis1Z + this.localAxis1Y * this.localAxis1Y;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- // make angle axis 2
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- var tarc = arc.elements;
- this.localAngAxis2X = this.localAngAxis1X * tarc[0] + this.localAngAxis1Y * tarc[1] + this.localAngAxis1Z * tarc[2];
- this.localAngAxis2Y = this.localAngAxis1X * tarc[3] + this.localAngAxis1Y * tarc[4] + this.localAngAxis1Z * tarc[5];
- this.localAngAxis2Z = this.localAngAxis1X * tarc[6] + this.localAngAxis1Y * tarc[7] + this.localAngAxis1Z * tarc[8];
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- // The limit and motor for the rotation
- this.rotationalLimitMotor = new OIMO.LimitMotor(this.nor, false);
- this.r3 = new OIMO.Rotational3Constraint(this, this.rotationalLimitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- // The limit and motor for the translation.
- this.translationalLimitMotor = new OIMO.LimitMotor(this.nor, true);
- this.translationalLimitMotor.lowerLimit = lowerTranslation;
- this.translationalLimitMotor.upperLimit = upperTranslation;
- this.t3 = new OIMO.Translational3Constraint(this, this.translationalLimitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.SliderJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.SliderJoint.prototype.constructor = OIMO.SliderJoint;
- OIMO.SliderJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var axis1X = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var axis1Y = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var axis1Z = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- var angAxis1X = this.localAngAxis1X * tmpM[0] + this.localAngAxis1Y * tmpM[1] + this.localAngAxis1Z * tmpM[2];
- var angAxis1Y = this.localAngAxis1X * tmpM[3] + this.localAngAxis1Y * tmpM[4] + this.localAngAxis1Z * tmpM[5];
- var angAxis1Z = this.localAngAxis1X * tmpM[6] + this.localAngAxis1Y * tmpM[7] + this.localAngAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var axis2X = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var axis2Y = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var axis2Z = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var angAxis2X = this.localAngAxis2X * tmpM[0] + this.localAngAxis2Y * tmpM[1] + this.localAngAxis2Z * tmpM[2];
- var angAxis2Y = this.localAngAxis2X * tmpM[3] + this.localAngAxis2Y * tmpM[4] + this.localAngAxis2Z * tmpM[5];
- var angAxis2Z = this.localAngAxis2X * tmpM[6] + this.localAngAxis2Y * tmpM[7] + this.localAngAxis2Z * tmpM[8];
- var nx = axis1X * this.body2.inverseMass + axis2X * this.body1.inverseMass;
- var ny = axis1Y * this.body2.inverseMass + axis2Y * this.body1.inverseMass;
- var nz = axis1Z * this.body2.inverseMass + axis2Z * this.body1.inverseMass;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * nx - nz * nz;
- var ty = -nz * ny - nx * nx;
- var tz = nx * nz + ny * ny;
- tmp1X = 1 / OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = ny * tz - nz * ty;
- var by = nz * tx - nx * tz;
- var bz = nx * ty - ny * tx;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- // ----------------------------------------------
- // calculate hinge angle
- // ----------------------------------------------
- if (
- nx * (angAxis1Y * angAxis2Z - angAxis1Z * angAxis2Y) +
- ny * (angAxis1Z * angAxis2X - angAxis1X * angAxis2Z) +
- nz * (angAxis1X * angAxis2Y - angAxis1Y * angAxis2X) < 0
- ) {
- this.rotationalLimitMotor.angle = -this.acosClamp(angAxis1X * angAxis2X + angAxis1Y * angAxis2Y + angAxis1Z * angAxis2Z);
- } else {
- this.rotationalLimitMotor.angle = this.acosClamp(angAxis1X * angAxis2X + angAxis1Y * angAxis2Y + angAxis1Z * angAxis2Z);
- }
- // angular error
- tmp1X = axis1Y * axis2Z - axis1Z * axis2Y;
- tmp1Y = axis1Z * axis2X - axis1X * axis2Z;
- tmp1Z = axis1X * axis2Y - axis1Y * axis2X;
- this.r3.limitMotor2.angle = tx * tmp1X + ty * tmp1Y + tz * tmp1Z;
- this.r3.limitMotor3.angle = bx * tmp1X + by * tmp1Y + bz * tmp1Z;
- this.r3.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.SliderJoint.prototype.solve = function () {
- this.r3.solve();
- this.t3.solve();
- };
- OIMO.SliderJoint.prototype.postSolve = function () {
- };
- OIMO.SliderJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * A wheel joint allows for relative rotation between two rigid bodies along two axes.
- * The wheel joint also allows for relative translation for the suspension.
- * @author saharan
- * @author lo-th
- */
- OIMO.WheelJoint = function (config) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_WHEEL;
- // The first axis in local coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The second axis in local coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- var len;
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- var dot = this.localAxis1X * this.localAxis2X + this.localAxis1Y * this.localAxis2Y + this.localAxis1Z * this.localAxis2Z;
- if (dot > -1 && dot < 1) {
- this.localAngAxis1X = this.localAxis2X - dot * this.localAxis1X;
- this.localAngAxis1Y = this.localAxis2Y - dot * this.localAxis1Y;
- this.localAngAxis1Z = this.localAxis2Z - dot * this.localAxis1Z;
- this.localAngAxis2X = this.localAxis1X - dot * this.localAxis2X;
- this.localAngAxis2Y = this.localAxis1Y - dot * this.localAxis2Y;
- this.localAngAxis2Z = this.localAxis1Z - dot * this.localAxis2Z;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- len = 1 / OIMO.sqrt(this.localAngAxis2X * this.localAngAxis2X + this.localAngAxis2Y * this.localAngAxis2Y + this.localAngAxis2Z * this.localAngAxis2Z);
- this.localAngAxis2X *= len;
- this.localAngAxis2Y *= len;
- this.localAngAxis2Z *= len;
- } else {
- this.localAngAxis1X = this.localAxis1Y * this.localAxis1X - this.localAxis1Z * this.localAxis1Z;
- this.localAngAxis1Y = -this.localAxis1Z * this.localAxis1Y - this.localAxis1X * this.localAxis1X;
- this.localAngAxis1Z = this.localAxis1X * this.localAxis1Z + this.localAxis1Y * this.localAxis1Y;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- var tarc = arc.elements;
- this.localAngAxis2X = this.localAngAxis1X * tarc[0] + this.localAngAxis1Y * tarc[1] + this.localAngAxis1Z * tarc[2];
- this.localAngAxis2Y = this.localAngAxis1X * tarc[3] + this.localAngAxis1Y * tarc[4] + this.localAngAxis1Z * tarc[5];
- this.localAngAxis2Z = this.localAngAxis1X * tarc[6] + this.localAngAxis1Y * tarc[7] + this.localAngAxis1Z * tarc[8];
- }
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- // The translational limit and motor information of the joint.
- this.translationalLimitMotor = new OIMO.LimitMotor(this.tan, true);
- this.translationalLimitMotor.frequency = 8;
- this.translationalLimitMotor.dampingRatio = 1;
- // The first rotational limit and motor information of the joint.
- this.rotationalLimitMotor1 = new OIMO.LimitMotor(this.tan, false);
- // The second rotational limit and motor information of the joint.
- this.rotationalLimitMotor2 = new OIMO.LimitMotor(this.bin, false);
- this.t3 = new OIMO.Translational3Constraint(this, new OIMO.LimitMotor(this.nor, true), this.translationalLimitMotor, new OIMO.LimitMotor(this.bin, true));
- this.t3.weight = 1;
- this.r3 = new OIMO.Rotational3Constraint(this, new OIMO.LimitMotor(this.nor, true), this.rotationalLimitMotor1, this.rotationalLimitMotor2);
- };
- OIMO.WheelJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.WheelJoint.prototype.constructor = OIMO.WheelJoint;
- OIMO.WheelJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var x1 = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var y1 = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var z1 = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- var angAxis1X = this.localAngAxis1X * tmpM[0] + this.localAngAxis1Y * tmpM[1] + this.localAngAxis1Z * tmpM[2];
- var angAxis1Y = this.localAngAxis1X * tmpM[3] + this.localAngAxis1Y * tmpM[4] + this.localAngAxis1Z * tmpM[5];
- var angAxis1Z = this.localAngAxis1X * tmpM[6] + this.localAngAxis1Y * tmpM[7] + this.localAngAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var x2 = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var y2 = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var z2 = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var angAxis2X = this.localAngAxis2X * tmpM[0] + this.localAngAxis2Y * tmpM[1] + this.localAngAxis2Z * tmpM[2];
- var angAxis2Y = this.localAngAxis2X * tmpM[3] + this.localAngAxis2Y * tmpM[4] + this.localAngAxis2Z * tmpM[5];
- var angAxis2Z = this.localAngAxis2X * tmpM[6] + this.localAngAxis2Y * tmpM[7] + this.localAngAxis2Z * tmpM[8];
- this.r3.limitMotor1.angle = x1 * x2 + y1 * y2 + z1 * z2;
- if (x1 * (angAxis1Y * z2 - angAxis1Z * y2) + y1 * (angAxis1Z * x2 - angAxis1X * z2) + z1 * (angAxis1X * y2 - angAxis1Y * x2) < 0) {
- this.rotationalLimitMotor1.angle = -this.acosClamp(angAxis1X * x2 + angAxis1Y * y2 + angAxis1Z * z2);
- } else {
- this.rotationalLimitMotor1.angle = this.acosClamp(angAxis1X * x2 + angAxis1Y * y2 + angAxis1Z * z2);
- }
- if (x2 * (angAxis2Y * z1 - angAxis2Z * y1) + y2 * (angAxis2Z * x1 - angAxis2X * z1) + z2 * (angAxis2X * y1 - angAxis2Y * x1) < 0) {
- this.rotationalLimitMotor2.angle = this.acosClamp(angAxis2X * x1 + angAxis2Y * y1 + angAxis2Z * z1);
- } else {
- this.rotationalLimitMotor2.angle = -this.acosClamp(angAxis2X * x1 + angAxis2Y * y1 + angAxis2Z * z1);
- }
- var nx = y2 * z1 - z2 * y1;
- var ny = z2 * x1 - x2 * z1;
- var nz = x2 * y1 - y2 * x1;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * z2 - nz * y2;
- var ty = nz * x2 - nx * z2;
- var tz = nx * y2 - ny * x2;
- tmp1X = OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = y1 * nz - z1 * ny;
- var by = z1 * nx - x1 * nz;
- var bz = x1 * ny - y1 * nx;
- tmp1X = OIMO.sqrt(bx * bx + by * by + bz * bz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- bx *= tmp1X;
- by *= tmp1X;
- bz *= tmp1X;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- this.r3.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.WheelJoint.prototype.solve = function () {
- this.r3.solve();
- this.t3.solve();
- };
- OIMO.WheelJoint.prototype.postSolve = function () {
- };
- OIMO.WheelJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * An angular constraint for all axes for various joints.
- * @author saharan
- */
- OIMO.AngularConstraint = function (joint, targetOrientation) {
- this.joint = joint;
- this.targetOrientation = new OIMO.Quat().invert(targetOrientation);
- this.relativeOrientation = new OIMO.Quat();
- this.ii1 = null;
- this.ii2 = null;
- this.dd = null;
- this.vel = new OIMO.Vec3();
- this.imp = new OIMO.Vec3();
- this.rn0 = new OIMO.Vec3();
- this.rn1 = new OIMO.Vec3();
- this.rn2 = new OIMO.Vec3();
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- };
- OIMO.AngularConstraint.prototype = {
- constructor: OIMO.AngularConstraint,
- preSolve: function (timeStep, invTimeStep) {
- var inv, len, v, vv;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- v = new OIMO.Mat33().add(this.ii1, this.ii2).elements;
- inv = 1 / (v[0] * (v[4] * v[8] - v[7] * v[5]) + v[3] * (v[7] * v[2] - v[1] * v[8]) + v[6] * (v[1] * v[5] - v[4] * v[2]));
- this.dd = new OIMO.Mat33(
- v[4] * v[8] - v[5] * v[7], v[2] * v[7] - v[1] * v[8], v[1] * v[5] - v[2] * v[4],
- v[5] * v[6] - v[3] * v[8], v[0] * v[8] - v[2] * v[6], v[2] * v[3] - v[0] * v[5],
- v[3] * v[7] - v[4] * v[6], v[1] * v[6] - v[0] * v[7], v[0] * v[4] - v[1] * v[3]
- ).multiply(inv);
- this.relativeOrientation.invert(this.b1.orientation);
- this.relativeOrientation.mul(this.targetOrientation, this.relativeOrientation);
- this.relativeOrientation.mul(this.b2.orientation, this.relativeOrientation);
- inv = this.relativeOrientation.s * 2;
- this.vel.scale(this.relativeOrientation, inv);
- len = this.vel.length();
- if (len > 0.02) {
- len = (0.02 - len) / len * invTimeStep * 0.05;
- this.vel.scaleEqual(len);
- } else {
- this.vel.init();
- }
- this.rn1.mulMat(this.ii1, this.imp);
- this.rn2.mulMat(this.ii2, this.imp);
- this.a1.addEqual(this.rn1);
- this.a2.subEqual(this.rn2);
- },
- solve: function () {
- var r = this.a2.clone().subEqual(this.a1).subEqual(this.vel);
- this.rn0.mulMat(this.dd, r);
- this.rn1.mulMat(this.ii1, this.rn0);
- this.rn2.mulMat(this.ii2, this.rn0);
- this.imp.addEqual(this.rn0);
- this.a1.addEqual(this.rn1);
- this.a2.subEqual(this.rn2);
- }
- };
- /**
- * A linear constraint for all axes for various joints.
- * @author saharan
- */
- OIMO.LinearConstraint = function (joint) {
- this.m1 = NaN;
- this.m2 = NaN;
- this.ii1 = null;
- this.ii2 = null;
- this.dd = null;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.ax1x = NaN;
- this.ax1y = NaN;
- this.ax1z = NaN;
- this.ay1x = NaN;
- this.ay1y = NaN;
- this.ay1z = NaN;
- this.az1x = NaN;
- this.az1y = NaN;
- this.az1z = NaN;
- this.ax2x = NaN;
- this.ax2y = NaN;
- this.ax2z = NaN;
- this.ay2x = NaN;
- this.ay2y = NaN;
- this.ay2z = NaN;
- this.az2x = NaN;
- this.az2y = NaN;
- this.az2z = NaN;
- this.vel = NaN;
- this.velx = NaN;
- this.vely = NaN;
- this.velz = NaN;
- this.joint = joint;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.impx = 0;
- this.impy = 0;
- this.impz = 0;
- }
- OIMO.LinearConstraint.prototype = {
- constructor: OIMO.LinearConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.r1x = this.r1.x;
- this.r1y = this.r1.y;
- this.r1z = this.r1.z;
- this.r2x = this.r2.x;
- this.r2y = this.r2.y;
- this.r2z = this.r2.z;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- var ii1 = this.ii1.elements;
- var ii2 = this.ii2.elements;
- this.ax1x = this.r1z * ii1[1] + -this.r1y * ii1[2];
- this.ax1y = this.r1z * ii1[4] + -this.r1y * ii1[5];
- this.ax1z = this.r1z * ii1[7] + -this.r1y * ii1[8];
- this.ay1x = -this.r1z * ii1[0] + this.r1x * ii1[2];
- this.ay1y = -this.r1z * ii1[3] + this.r1x * ii1[5];
- this.ay1z = -this.r1z * ii1[6] + this.r1x * ii1[8];
- this.az1x = this.r1y * ii1[0] + -this.r1x * ii1[1];
- this.az1y = this.r1y * ii1[3] + -this.r1x * ii1[4];
- this.az1z = this.r1y * ii1[6] + -this.r1x * ii1[7];
- this.ax2x = this.r2z * ii2[1] + -this.r2y * ii2[2];
- this.ax2y = this.r2z * ii2[4] + -this.r2y * ii2[5];
- this.ax2z = this.r2z * ii2[7] + -this.r2y * ii2[8];
- this.ay2x = -this.r2z * ii2[0] + this.r2x * ii2[2];
- this.ay2y = -this.r2z * ii2[3] + this.r2x * ii2[5];
- this.ay2z = -this.r2z * ii2[6] + this.r2x * ii2[8];
- this.az2x = this.r2y * ii2[0] + -this.r2x * ii2[1];
- this.az2y = this.r2y * ii2[3] + -this.r2x * ii2[4];
- this.az2z = this.r2y * ii2[6] + -this.r2x * ii2[7];
- // calculate point-to-point mass matrix
- // from impulse equation
- //
- // M = ([/m] - [r^][/I][r^]) ^ -1
- //
- // where
- //
- // [/m] = |1/m, 0, 0|
- // |0, 1/m, 0|
- // |0, 0, 1/m|
- //
- // [r^] = |0, -rz, ry|
- // |rz, 0, -rx|
- // |-ry, rx, 0|
- //
- // [/I] = Inverted moment inertia
- var rxx = this.m1 + this.m2;
- var kk = new OIMO.Mat33(rxx, 0, 0, 0, rxx, 0, 0, 0, rxx);
- var k = kk.elements;
- k[0] += ii1[4] * this.r1z * this.r1z - (ii1[7] + ii1[5]) * this.r1y * this.r1z + ii1[8] * this.r1y * this.r1y;
- k[1] += (ii1[6] * this.r1y + ii1[5] * this.r1x) * this.r1z - ii1[3] * this.r1z * this.r1z - ii1[8] * this.r1x * this.r1y;
- k[2] += (ii1[3] * this.r1y - ii1[4] * this.r1x) * this.r1z - ii1[6] * this.r1y * this.r1y + ii1[7] * this.r1x * this.r1y;
- k[3] += (ii1[2] * this.r1y + ii1[7] * this.r1x) * this.r1z - ii1[1] * this.r1z * this.r1z - ii1[8] * this.r1x * this.r1y;
- k[4] += ii1[0] * this.r1z * this.r1z - (ii1[6] + ii1[2]) * this.r1x * this.r1z + ii1[8] * this.r1x * this.r1x;
- k[5] += (ii1[1] * this.r1x - ii1[0] * this.r1y) * this.r1z - ii1[7] * this.r1x * this.r1x + ii1[6] * this.r1x * this.r1y;
- k[6] += (ii1[1] * this.r1y - ii1[4] * this.r1x) * this.r1z - ii1[2] * this.r1y * this.r1y + ii1[5] * this.r1x * this.r1y;
- k[7] += (ii1[3] * this.r1x - ii1[0] * this.r1y) * this.r1z - ii1[5] * this.r1x * this.r1x + ii1[2] * this.r1x * this.r1y;
- k[8] += ii1[0] * this.r1y * this.r1y - (ii1[3] + ii1[1]) * this.r1x * this.r1y + ii1[4] * this.r1x * this.r1x;
- k[0] += ii2[4] * this.r2z * this.r2z - (ii2[7] + ii2[5]) * this.r2y * this.r2z + ii2[8] * this.r2y * this.r2y;
- k[1] += (ii2[6] * this.r2y + ii2[5] * this.r2x) * this.r2z - ii2[3] * this.r2z * this.r2z - ii2[8] * this.r2x * this.r2y;
- k[2] += (ii2[3] * this.r2y - ii2[4] * this.r2x) * this.r2z - ii2[6] * this.r2y * this.r2y + ii2[7] * this.r2x * this.r2y;
- k[3] += (ii2[2] * this.r2y + ii2[7] * this.r2x) * this.r2z - ii2[1] * this.r2z * this.r2z - ii2[8] * this.r2x * this.r2y;
- k[4] += ii2[0] * this.r2z * this.r2z - (ii2[6] + ii2[2]) * this.r2x * this.r2z + ii2[8] * this.r2x * this.r2x;
- k[5] += (ii2[1] * this.r2x - ii2[0] * this.r2y) * this.r2z - ii2[7] * this.r2x * this.r2x + ii2[6] * this.r2x * this.r2y;
- k[6] += (ii2[1] * this.r2y - ii2[4] * this.r2x) * this.r2z - ii2[2] * this.r2y * this.r2y + ii2[5] * this.r2x * this.r2y;
- k[7] += (ii2[3] * this.r2x - ii2[0] * this.r2y) * this.r2z - ii2[5] * this.r2x * this.r2x + ii2[2] * this.r2x * this.r2y;
- k[8] += ii2[0] * this.r2y * this.r2y - (ii2[3] + ii2[1]) * this.r2x * this.r2y + ii2[4] * this.r2x * this.r2x;
- var inv = 1 / (k[0] * (k[4] * k[8] - k[7] * k[5]) + k[3] * (k[7] * k[2] - k[1] * k[8]) + k[6] * (k[1] * k[5] - k[4] * k[2]));
- this.dd = new OIMO.Mat33(
- k[4] * k[8] - k[5] * k[7], k[2] * k[7] - k[1] * k[8], k[1] * k[5] - k[2] * k[4],
- k[5] * k[6] - k[3] * k[8], k[0] * k[8] - k[2] * k[6], k[2] * k[3] - k[0] * k[5],
- k[3] * k[7] - k[4] * k[6], k[1] * k[6] - k[0] * k[7], k[0] * k[4] - k[1] * k[3]
- ).multiply(inv);
- this.velx = this.p2.x - this.p1.x;
- this.vely = this.p2.y - this.p1.y;
- this.velz = this.p2.z - this.p1.z;
- var len = OIMO.sqrt(this.velx * this.velx + this.vely * this.vely + this.velz * this.velz);
- if (len > 0.005) {
- len = (0.005 - len) / len * invTimeStep * 0.05;
- this.velx *= len;
- this.vely *= len;
- this.velz *= len;
- } else {
- this.velx = 0;
- this.vely = 0;
- this.velz = 0;
- }
- this.impx *= 0.95;
- this.impy *= 0.95;
- this.impz *= 0.95;
- this.l1.x += this.impx * this.m1;
- this.l1.y += this.impy * this.m1;
- this.l1.z += this.impz * this.m1;
- this.a1.x += this.impx * this.ax1x + this.impy * this.ay1x + this.impz * this.az1x;
- this.a1.y += this.impx * this.ax1y + this.impy * this.ay1y + this.impz * this.az1y;
- this.a1.z += this.impx * this.ax1z + this.impy * this.ay1z + this.impz * this.az1z;
- this.l2.x -= this.impx * this.m2;
- this.l2.y -= this.impy * this.m2;
- this.l2.z -= this.impz * this.m2;
- this.a2.x -= this.impx * this.ax2x + this.impy * this.ay2x + this.impz * this.az2x;
- this.a2.y -= this.impx * this.ax2y + this.impy * this.ay2y + this.impz * this.az2y;
- this.a2.z -= this.impx * this.ax2z + this.impy * this.ay2z + this.impz * this.az2z;
- },
- solve: function () {
- var d = this.dd.elements;
- var rvx = this.l2.x - this.l1.x + this.a2.y * this.r2z - this.a2.z * this.r2y - this.a1.y * this.r1z + this.a1.z * this.r1y - this.velx;
- var rvy = this.l2.y - this.l1.y + this.a2.z * this.r2x - this.a2.x * this.r2z - this.a1.z * this.r1x + this.a1.x * this.r1z - this.vely;
- var rvz = this.l2.z - this.l1.z + this.a2.x * this.r2y - this.a2.y * this.r2x - this.a1.x * this.r1y + this.a1.y * this.r1x - this.velz;
- var nimpx = rvx * d[0] + rvy * d[1] + rvz * d[2];
- var nimpy = rvx * d[3] + rvy * d[4] + rvz * d[5];
- var nimpz = rvx * d[6] + rvy * d[7] + rvz * d[8];
- this.impx += nimpx;
- this.impy += nimpy;
- this.impz += nimpz;
- this.l1.x += nimpx * this.m1;
- this.l1.y += nimpy * this.m1;
- this.l1.z += nimpz * this.m1;
- this.a1.x += nimpx * this.ax1x + nimpy * this.ay1x + nimpz * this.az1x;
- this.a1.y += nimpx * this.ax1y + nimpy * this.ay1y + nimpz * this.az1y;
- this.a1.z += nimpx * this.ax1z + nimpy * this.ay1z + nimpz * this.az1z;
- this.l2.x -= nimpx * this.m2;
- this.l2.y -= nimpy * this.m2;
- this.l2.z -= nimpz * this.m2;
- this.a2.x -= nimpx * this.ax2x + nimpy * this.ay2x + nimpz * this.az2x;
- this.a2.y -= nimpx * this.ax2y + nimpy * this.ay2y + nimpz * this.az2y;
- this.a2.z -= nimpx * this.ax2z + nimpy * this.ay2z + nimpz * this.az2z;
- }
- }
- /**
- * A three-axis rotational constraint for various joints.
- * @author saharan
- */
- OIMO.Rotational3Constraint = function (joint, limitMotor1, limitMotor2, limitMotor3) {
- this.cfm1 = NaN;
- this.cfm2 = NaN;
- this.cfm3 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.ax1 = NaN;
- this.ay1 = NaN;
- this.az1 = NaN;
- this.ax2 = NaN;
- this.ay2 = NaN;
- this.az2 = NaN;
- this.ax3 = NaN;
- this.ay3 = NaN;
- this.az3 = NaN;
- this.a1x1 = NaN; // jacoians
- this.a1y1 = NaN;
- this.a1z1 = NaN;
- this.a2x1 = NaN;
- this.a2y1 = NaN;
- this.a2z1 = NaN;
- this.a1x2 = NaN;
- this.a1y2 = NaN;
- this.a1z2 = NaN;
- this.a2x2 = NaN;
- this.a2y2 = NaN;
- this.a2z2 = NaN;
- this.a1x3 = NaN;
- this.a1y3 = NaN;
- this.a1z3 = NaN;
- this.a2x3 = NaN;
- this.a2y3 = NaN;
- this.a2z3 = NaN;
- this.lowerLimit1 = NaN;
- this.upperLimit1 = NaN;
- this.limitVelocity1 = NaN;
- this.limitState1 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor1 = false;
- this.motorSpeed1 = NaN;
- this.maxMotorForce1 = NaN;
- this.maxMotorImpulse1 = NaN;
- this.lowerLimit2 = NaN;
- this.upperLimit2 = NaN;
- this.limitVelocity2 = NaN;
- this.limitState2 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor2 = false;
- this.motorSpeed2 = NaN;
- this.maxMotorForce2 = NaN;
- this.maxMotorImpulse2 = NaN;
- this.lowerLimit3 = NaN;
- this.upperLimit3 = NaN;
- this.limitVelocity3 = NaN;
- this.limitState3 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor3 = false;
- this.motorSpeed3 = NaN;
- this.maxMotorForce3 = NaN;
- this.maxMotorImpulse3 = NaN;
- this.k00 = NaN; // K = J*M*JT
- this.k01 = NaN;
- this.k02 = NaN;
- this.k10 = NaN;
- this.k11 = NaN;
- this.k12 = NaN;
- this.k20 = NaN;
- this.k21 = NaN;
- this.k22 = NaN;
- this.kv00 = NaN; // diagonals without CFMs
- this.kv11 = NaN;
- this.kv22 = NaN;
- this.dv00 = NaN; // ...inverted
- this.dv11 = NaN;
- this.dv22 = NaN;
- this.d00 = NaN; // K^-1
- this.d01 = NaN;
- this.d02 = NaN;
- this.d10 = NaN;
- this.d11 = NaN;
- this.d12 = NaN;
- this.d20 = NaN;
- this.d21 = NaN;
- this.d22 = NaN;
- this.limitMotor1 = limitMotor1;
- this.limitMotor2 = limitMotor2;
- this.limitMotor3 = limitMotor3;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse1 = 0;
- this.motorImpulse1 = 0;
- this.limitImpulse2 = 0;
- this.motorImpulse2 = 0;
- this.limitImpulse3 = 0;
- this.motorImpulse3 = 0;
- }
- OIMO.Rotational3Constraint.prototype = {
- constructor: OIMO.Rotational3Constraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax1 = this.limitMotor1.axis.x;
- this.ay1 = this.limitMotor1.axis.y;
- this.az1 = this.limitMotor1.axis.z;
- this.ax2 = this.limitMotor2.axis.x;
- this.ay2 = this.limitMotor2.axis.y;
- this.az2 = this.limitMotor2.axis.z;
- this.ax3 = this.limitMotor3.axis.x;
- this.ay3 = this.limitMotor3.axis.y;
- this.az3 = this.limitMotor3.axis.z;
- this.lowerLimit1 = this.limitMotor1.lowerLimit;
- this.upperLimit1 = this.limitMotor1.upperLimit;
- this.motorSpeed1 = this.limitMotor1.motorSpeed;
- this.maxMotorForce1 = this.limitMotor1.maxMotorForce;
- this.enableMotor1 = this.maxMotorForce1 > 0;
- this.lowerLimit2 = this.limitMotor2.lowerLimit;
- this.upperLimit2 = this.limitMotor2.upperLimit;
- this.motorSpeed2 = this.limitMotor2.motorSpeed;
- this.maxMotorForce2 = this.limitMotor2.maxMotorForce;
- this.enableMotor2 = this.maxMotorForce2 > 0;
- this.lowerLimit3 = this.limitMotor3.lowerLimit;
- this.upperLimit3 = this.limitMotor3.upperLimit;
- this.motorSpeed3 = this.limitMotor3.motorSpeed;
- this.maxMotorForce3 = this.limitMotor3.maxMotorForce;
- this.enableMotor3 = this.maxMotorForce3 > 0;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var frequency1 = this.limitMotor1.frequency;
- var frequency2 = this.limitMotor2.frequency;
- var frequency3 = this.limitMotor3.frequency;
- var enableSpring1 = frequency1 > 0;
- var enableSpring2 = frequency2 > 0;
- var enableSpring3 = frequency3 > 0;
- var enableLimit1 = this.lowerLimit1 <= this.upperLimit1;
- var enableLimit2 = this.lowerLimit2 <= this.upperLimit2;
- var enableLimit3 = this.lowerLimit3 <= this.upperLimit3;
- var angle1 = this.limitMotor1.angle;
- if (enableLimit1) {
- if (this.lowerLimit1 == this.upperLimit1) {
- if (this.limitState1 != 0) {
- this.limitState1 = 0;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - angle1;
- } else if (angle1 < this.lowerLimit1) {
- if (this.limitState1 != -1) {
- this.limitState1 = -1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - angle1;
- } else if (angle1 > this.upperLimit1) {
- if (this.limitState1 != 1) {
- this.limitState1 = 1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.upperLimit1 - angle1;
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- this.limitVelocity1 = 0;
- }
- if (!enableSpring1) {
- if (this.limitVelocity1 > 0.02) this.limitVelocity1 -= 0.02;
- else if (this.limitVelocity1 < -0.02) this.limitVelocity1 += 0.02;
- else this.limitVelocity1 = 0;
- }
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- }
- var angle2 = this.limitMotor2.angle;
- if (enableLimit2) {
- if (this.lowerLimit2 == this.upperLimit2) {
- if (this.limitState2 != 0) {
- this.limitState2 = 0;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - angle2;
- } else if (angle2 < this.lowerLimit2) {
- if (this.limitState2 != -1) {
- this.limitState2 = -1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - angle2;
- } else if (angle2 > this.upperLimit2) {
- if (this.limitState2 != 1) {
- this.limitState2 = 1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.upperLimit2 - angle2;
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- this.limitVelocity2 = 0;
- }
- if (!enableSpring2) {
- if (this.limitVelocity2 > 0.02) this.limitVelocity2 -= 0.02;
- else if (this.limitVelocity2 < -0.02) this.limitVelocity2 += 0.02;
- else this.limitVelocity2 = 0;
- }
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- }
- var angle3 = this.limitMotor3.angle;
- if (enableLimit3) {
- if (this.lowerLimit3 == this.upperLimit3) {
- if (this.limitState3 != 0) {
- this.limitState3 = 0;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - angle3;
- } else if (angle3 < this.lowerLimit3) {
- if (this.limitState3 != -1) {
- this.limitState3 = -1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - angle3;
- } else if (angle3 > this.upperLimit3) {
- if (this.limitState3 != 1) {
- this.limitState3 = 1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.upperLimit3 - angle3;
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- this.limitVelocity3 = 0;
- }
- if (!enableSpring3) {
- if (this.limitVelocity3 > 0.02) this.limitVelocity3 -= 0.02;
- else if (this.limitVelocity3 < -0.02) this.limitVelocity3 += 0.02;
- else this.limitVelocity3 = 0;
- }
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- }
- if (this.enableMotor1 && (this.limitState1 != 0 || enableSpring1)) {
- this.maxMotorImpulse1 = this.maxMotorForce1 * timeStep;
- } else {
- this.motorImpulse1 = 0;
- this.maxMotorImpulse1 = 0;
- }
- if (this.enableMotor2 && (this.limitState2 != 0 || enableSpring2)) {
- this.maxMotorImpulse2 = this.maxMotorForce2 * timeStep;
- } else {
- this.motorImpulse2 = 0;
- this.maxMotorImpulse2 = 0;
- }
- if (this.enableMotor3 && (this.limitState3 != 0 || enableSpring3)) {
- this.maxMotorImpulse3 = this.maxMotorForce3 * timeStep;
- } else {
- this.motorImpulse3 = 0;
- this.maxMotorImpulse3 = 0;
- }
- // build jacobians
- this.a1x1 = this.ax1 * this.i1e00 + this.ay1 * this.i1e01 + this.az1 * this.i1e02;
- this.a1y1 = this.ax1 * this.i1e10 + this.ay1 * this.i1e11 + this.az1 * this.i1e12;
- this.a1z1 = this.ax1 * this.i1e20 + this.ay1 * this.i1e21 + this.az1 * this.i1e22;
- this.a2x1 = this.ax1 * this.i2e00 + this.ay1 * this.i2e01 + this.az1 * this.i2e02;
- this.a2y1 = this.ax1 * this.i2e10 + this.ay1 * this.i2e11 + this.az1 * this.i2e12;
- this.a2z1 = this.ax1 * this.i2e20 + this.ay1 * this.i2e21 + this.az1 * this.i2e22;
- this.a1x2 = this.ax2 * this.i1e00 + this.ay2 * this.i1e01 + this.az2 * this.i1e02;
- this.a1y2 = this.ax2 * this.i1e10 + this.ay2 * this.i1e11 + this.az2 * this.i1e12;
- this.a1z2 = this.ax2 * this.i1e20 + this.ay2 * this.i1e21 + this.az2 * this.i1e22;
- this.a2x2 = this.ax2 * this.i2e00 + this.ay2 * this.i2e01 + this.az2 * this.i2e02;
- this.a2y2 = this.ax2 * this.i2e10 + this.ay2 * this.i2e11 + this.az2 * this.i2e12;
- this.a2z2 = this.ax2 * this.i2e20 + this.ay2 * this.i2e21 + this.az2 * this.i2e22;
- this.a1x3 = this.ax3 * this.i1e00 + this.ay3 * this.i1e01 + this.az3 * this.i1e02;
- this.a1y3 = this.ax3 * this.i1e10 + this.ay3 * this.i1e11 + this.az3 * this.i1e12;
- this.a1z3 = this.ax3 * this.i1e20 + this.ay3 * this.i1e21 + this.az3 * this.i1e22;
- this.a2x3 = this.ax3 * this.i2e00 + this.ay3 * this.i2e01 + this.az3 * this.i2e02;
- this.a2y3 = this.ax3 * this.i2e10 + this.ay3 * this.i2e11 + this.az3 * this.i2e12;
- this.a2z3 = this.ax3 * this.i2e20 + this.ay3 * this.i2e21 + this.az3 * this.i2e22;
- // build an impulse matrix
- this.k00 = this.ax1 * (this.a1x1 + this.a2x1) + this.ay1 * (this.a1y1 + this.a2y1) + this.az1 * (this.a1z1 + this.a2z1);
- this.k01 = this.ax1 * (this.a1x2 + this.a2x2) + this.ay1 * (this.a1y2 + this.a2y2) + this.az1 * (this.a1z2 + this.a2z2);
- this.k02 = this.ax1 * (this.a1x3 + this.a2x3) + this.ay1 * (this.a1y3 + this.a2y3) + this.az1 * (this.a1z3 + this.a2z3);
- this.k10 = this.ax2 * (this.a1x1 + this.a2x1) + this.ay2 * (this.a1y1 + this.a2y1) + this.az2 * (this.a1z1 + this.a2z1);
- this.k11 = this.ax2 * (this.a1x2 + this.a2x2) + this.ay2 * (this.a1y2 + this.a2y2) + this.az2 * (this.a1z2 + this.a2z2);
- this.k12 = this.ax2 * (this.a1x3 + this.a2x3) + this.ay2 * (this.a1y3 + this.a2y3) + this.az2 * (this.a1z3 + this.a2z3);
- this.k20 = this.ax3 * (this.a1x1 + this.a2x1) + this.ay3 * (this.a1y1 + this.a2y1) + this.az3 * (this.a1z1 + this.a2z1);
- this.k21 = this.ax3 * (this.a1x2 + this.a2x2) + this.ay3 * (this.a1y2 + this.a2y2) + this.az3 * (this.a1z2 + this.a2z2);
- this.k22 = this.ax3 * (this.a1x3 + this.a2x3) + this.ay3 * (this.a1y3 + this.a2y3) + this.az3 * (this.a1z3 + this.a2z3);
- this.kv00 = this.k00;
- this.kv11 = this.k11;
- this.kv22 = this.k22;
- this.dv00 = 1 / this.kv00;
- this.dv11 = 1 / this.kv11;
- this.dv22 = 1 / this.kv22;
- if (enableSpring1 && this.limitState1 != 2) {
- var omega = 6.2831853 * frequency1;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor1.dampingRatio * omega);
- this.cfm1 = this.kv00 * dmp;
- this.limitVelocity1 *= k * dmp;
- } else {
- this.cfm1 = 0;
- this.limitVelocity1 *= invTimeStep * 0.05;
- }
- if (enableSpring2 && this.limitState2 != 2) {
- omega = 6.2831853 * frequency2;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor2.dampingRatio * omega);
- this.cfm2 = this.kv11 * dmp;
- this.limitVelocity2 *= k * dmp;
- } else {
- this.cfm2 = 0;
- this.limitVelocity2 *= invTimeStep * 0.05;
- }
- if (enableSpring3 && this.limitState3 != 2) {
- omega = 6.2831853 * frequency3;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor3.dampingRatio * omega);
- this.cfm3 = this.kv22 * dmp;
- this.limitVelocity3 *= k * dmp;
- } else {
- this.cfm3 = 0;
- this.limitVelocity3 *= invTimeStep * 0.05;
- }
- this.k00 += this.cfm1;
- this.k11 += this.cfm2;
- this.k22 += this.cfm3;
- var inv = 1 / (
- this.k00 * (this.k11 * this.k22 - this.k21 * this.k12) +
- this.k10 * (this.k21 * this.k02 - this.k01 * this.k22) +
- this.k20 * (this.k01 * this.k12 - this.k11 * this.k02)
- );
- this.d00 = (this.k11 * this.k22 - this.k12 * this.k21) * inv;
- this.d01 = (this.k02 * this.k21 - this.k01 * this.k22) * inv;
- this.d02 = (this.k01 * this.k12 - this.k02 * this.k11) * inv;
- this.d10 = (this.k12 * this.k20 - this.k10 * this.k22) * inv;
- this.d11 = (this.k00 * this.k22 - this.k02 * this.k20) * inv;
- this.d12 = (this.k02 * this.k10 - this.k00 * this.k12) * inv;
- this.d20 = (this.k10 * this.k21 - this.k11 * this.k20) * inv;
- this.d21 = (this.k01 * this.k20 - this.k00 * this.k21) * inv;
- this.d22 = (this.k00 * this.k11 - this.k01 * this.k10) * inv;
- this.limitImpulse1 *= 0.95;
- this.motorImpulse1 *= 0.95;
- this.limitImpulse2 *= 0.95;
- this.motorImpulse2 *= 0.95;
- this.limitImpulse3 *= 0.95;
- this.motorImpulse3 *= 0.95;
- var totalImpulse1 = this.limitImpulse1 + this.motorImpulse1;
- var totalImpulse2 = this.limitImpulse2 + this.motorImpulse2;
- var totalImpulse3 = this.limitImpulse3 + this.motorImpulse3;
- this.a1.x += totalImpulse1 * this.a1x1 + totalImpulse2 * this.a1x2 + totalImpulse3 * this.a1x3;
- this.a1.y += totalImpulse1 * this.a1y1 + totalImpulse2 * this.a1y2 + totalImpulse3 * this.a1y3;
- this.a1.z += totalImpulse1 * this.a1z1 + totalImpulse2 * this.a1z2 + totalImpulse3 * this.a1z3;
- this.a2.x -= totalImpulse1 * this.a2x1 + totalImpulse2 * this.a2x2 + totalImpulse3 * this.a2x3;
- this.a2.y -= totalImpulse1 * this.a2y1 + totalImpulse2 * this.a2y2 + totalImpulse3 * this.a2y3;
- this.a2.z -= totalImpulse1 * this.a2z1 + totalImpulse2 * this.a2z2 + totalImpulse3 * this.a2z3;
- },
- solve_: function () {
- var rvx = this.a2.x - this.a1.x;
- var rvy = this.a2.y - this.a1.y;
- var rvz = this.a2.z - this.a1.z;
- this.limitVelocity3 = 30;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1 - this.limitVelocity1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2 - this.limitVelocity2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3 - this.limitVelocity3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- this.a1.x += dLimitImpulse1 * this.a1x1 + dLimitImpulse2 * this.a1x2 + dLimitImpulse3 * this.a1x3;
- this.a1.y += dLimitImpulse1 * this.a1y1 + dLimitImpulse2 * this.a1y2 + dLimitImpulse3 * this.a1y3;
- this.a1.z += dLimitImpulse1 * this.a1z1 + dLimitImpulse2 * this.a1z2 + dLimitImpulse3 * this.a1z3;
- this.a2.x -= dLimitImpulse1 * this.a2x1 + dLimitImpulse2 * this.a2x2 + dLimitImpulse3 * this.a2x3;
- this.a2.y -= dLimitImpulse1 * this.a2y1 + dLimitImpulse2 * this.a2y2 + dLimitImpulse3 * this.a2y3;
- this.a2.z -= dLimitImpulse1 * this.a2z1 + dLimitImpulse2 * this.a2z2 + dLimitImpulse3 * this.a2z3;
- },
- solve: function () {
- var rvx = this.a2.x - this.a1.x;
- var rvy = this.a2.y - this.a1.y;
- var rvz = this.a2.z - this.a1.z;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3;
- var oldMotorImpulse1 = this.motorImpulse1;
- var oldMotorImpulse2 = this.motorImpulse2;
- var oldMotorImpulse3 = this.motorImpulse3;
- var dMotorImpulse1 = 0;
- var dMotorImpulse2 = 0;
- var dMotorImpulse3 = 0;
- if (this.enableMotor1) {
- dMotorImpulse1 = (rvn1 - this.motorSpeed1) * this.dv00;
- this.motorImpulse1 += dMotorImpulse1;
- if (this.motorImpulse1 > this.maxMotorImpulse1) { // clamp motor impulse
- this.motorImpulse1 = this.maxMotorImpulse1;
- } else if (this.motorImpulse1 < -this.maxMotorImpulse1) {
- this.motorImpulse1 = -this.maxMotorImpulse1;
- }
- dMotorImpulse1 = this.motorImpulse1 - oldMotorImpulse1;
- }
- if (this.enableMotor2) {
- dMotorImpulse2 = (rvn2 - this.motorSpeed2) * this.dv11;
- this.motorImpulse2 += dMotorImpulse2;
- if (this.motorImpulse2 > this.maxMotorImpulse2) { // clamp motor impulse
- this.motorImpulse2 = this.maxMotorImpulse2;
- } else if (this.motorImpulse2 < -this.maxMotorImpulse2) {
- this.motorImpulse2 = -this.maxMotorImpulse2;
- }
- dMotorImpulse2 = this.motorImpulse2 - oldMotorImpulse2;
- }
- if (this.enableMotor3) {
- dMotorImpulse3 = (rvn3 - this.motorSpeed3) * this.dv22;
- this.motorImpulse3 += dMotorImpulse3;
- if (this.motorImpulse3 > this.maxMotorImpulse3) { // clamp motor impulse
- this.motorImpulse3 = this.maxMotorImpulse3;
- } else if (this.motorImpulse3 < -this.maxMotorImpulse3) {
- this.motorImpulse3 = -this.maxMotorImpulse3;
- }
- dMotorImpulse3 = this.motorImpulse3 - oldMotorImpulse3;
- }
- // apply motor impulse to relative velocity
- rvn1 += dMotorImpulse1 * this.kv00 + dMotorImpulse2 * this.k01 + dMotorImpulse3 * this.k02;
- rvn2 += dMotorImpulse1 * this.k10 + dMotorImpulse2 * this.kv11 + dMotorImpulse3 * this.k12;
- rvn3 += dMotorImpulse1 * this.k20 + dMotorImpulse2 * this.k21 + dMotorImpulse3 * this.kv22;
- // subtract target velocity and applied impulse
- rvn1 -= this.limitVelocity1 + this.limitImpulse1 * this.cfm1;
- rvn2 -= this.limitVelocity2 + this.limitImpulse2 * this.cfm2;
- rvn3 -= this.limitVelocity3 + this.limitImpulse3 * this.cfm3;
- var oldLimitImpulse1 = this.limitImpulse1;
- var oldLimitImpulse2 = this.limitImpulse2;
- var oldLimitImpulse3 = this.limitImpulse3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- // clamp
- var clampState = 0;
- if (this.limitState1 == 2 || this.limitImpulse1 * this.limitState1 < 0) {
- dLimitImpulse1 = -oldLimitImpulse1;
- rvn2 += dLimitImpulse1 * this.k10;
- rvn3 += dLimitImpulse1 * this.k20;
- clampState |= 1;
- }
- if (this.limitState2 == 2 || this.limitImpulse2 * this.limitState2 < 0) {
- dLimitImpulse2 = -oldLimitImpulse2;
- rvn1 += dLimitImpulse2 * this.k01;
- rvn3 += dLimitImpulse2 * this.k21;
- clampState |= 2;
- }
- if (this.limitState3 == 2 || this.limitImpulse3 * this.limitState3 < 0) {
- dLimitImpulse3 = -oldLimitImpulse3;
- rvn1 += dLimitImpulse3 * this.k02;
- rvn2 += dLimitImpulse3 * this.k12;
- clampState |= 4;
- }
- // update un-clamped impulse
- // TODO: isolate division
- var det;
- switch (clampState) {
- case 1: // update 2 3
- det = 1 / (this.k11 * this.k22 - this.k12 * this.k21);
- dLimitImpulse2 = (this.k22 * rvn2 + -this.k12 * rvn3) * det;
- dLimitImpulse3 = (-this.k21 * rvn2 + this.k11 * rvn3) * det;
- break;
- case 2: // update 1 3
- det = 1 / (this.k00 * this.k22 - this.k02 * this.k20);
- dLimitImpulse1 = (this.k22 * rvn1 + -this.k02 * rvn3) * det;
- dLimitImpulse3 = (-this.k20 * rvn1 + this.k00 * rvn3) * det;
- break;
- case 3: // update 3
- dLimitImpulse3 = rvn3 / this.k22;
- break;
- case 4: // update 1 2
- det = 1 / (this.k00 * this.k11 - this.k01 * this.k10);
- dLimitImpulse1 = (this.k11 * rvn1 + -this.k01 * rvn2) * det;
- dLimitImpulse2 = (-this.k10 * rvn1 + this.k00 * rvn2) * det;
- break;
- case 5: // update 2
- dLimitImpulse2 = rvn2 / this.k11;
- break;
- case 6: // update 1
- dLimitImpulse1 = rvn1 / this.k00;
- break;
- }
- this.limitImpulse1 = dLimitImpulse1 + oldLimitImpulse1;
- this.limitImpulse2 = dLimitImpulse2 + oldLimitImpulse2;
- this.limitImpulse3 = dLimitImpulse3 + oldLimitImpulse3;
- var dImpulse1 = dMotorImpulse1 + dLimitImpulse1;
- var dImpulse2 = dMotorImpulse2 + dLimitImpulse2;
- var dImpulse3 = dMotorImpulse3 + dLimitImpulse3;
- // apply impulse
- this.a1.x += dImpulse1 * this.a1x1 + dImpulse2 * this.a1x2 + dImpulse3 * this.a1x3;
- this.a1.y += dImpulse1 * this.a1y1 + dImpulse2 * this.a1y2 + dImpulse3 * this.a1y3;
- this.a1.z += dImpulse1 * this.a1z1 + dImpulse2 * this.a1z2 + dImpulse3 * this.a1z3;
- this.a2.x -= dImpulse1 * this.a2x1 + dImpulse2 * this.a2x2 + dImpulse3 * this.a2x3;
- this.a2.y -= dImpulse1 * this.a2y1 + dImpulse2 * this.a2y2 + dImpulse3 * this.a2y3;
- this.a2.z -= dImpulse1 * this.a2z1 + dImpulse2 * this.a2z2 + dImpulse3 * this.a2z3;
- rvx = this.a2.x - this.a1.x;
- rvy = this.a2.y - this.a1.y;
- rvz = this.a2.z - this.a1.z;
- rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- }
- }
- /**
- * A rotational constraint for various joints.
- * @author saharan
- */
- OIMO.RotationalConstraint = function (joint, limitMotor) {
- this.cfm = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.motorDenom = NaN;
- this.invMotorDenom = NaN;
- this.invDenom = NaN;
- this.ax = NaN;
- this.ay = NaN;
- this.az = NaN;
- this.a1x = NaN;
- this.a1y = NaN;
- this.a1z = NaN;
- this.a2x = NaN;
- this.a2y = NaN;
- this.a2z = NaN;
- this.enableLimit = false;
- this.lowerLimit = NaN;
- this.upperLimit = NaN;
- this.limitVelocity = NaN;
- this.limitState = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor = false;
- this.motorSpeed = NaN;
- this.maxMotorForce = NaN;
- this.maxMotorImpulse = NaN;
- this.limitMotor = limitMotor;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse = 0;
- this.motorImpulse = 0;
- }
- OIMO.RotationalConstraint.prototype = {
- constructor: OIMO.RotationalConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax = this.limitMotor.axis.x;
- this.ay = this.limitMotor.axis.y;
- this.az = this.limitMotor.axis.z;
- this.lowerLimit = this.limitMotor.lowerLimit;
- this.upperLimit = this.limitMotor.upperLimit;
- this.motorSpeed = this.limitMotor.motorSpeed;
- this.maxMotorForce = this.limitMotor.maxMotorForce;
- this.enableMotor = this.maxMotorForce > 0;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var frequency = this.limitMotor.frequency;
- var enableSpring = frequency > 0;
- var enableLimit = this.lowerLimit <= this.upperLimit;
- var angle = this.limitMotor.angle;
- if (enableLimit) {
- if (this.lowerLimit == this.upperLimit) {
- if (this.limitState != 0) {
- this.limitState = 0;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - angle;
- } else if (angle < this.lowerLimit) {
- if (this.limitState != -1) {
- this.limitState = -1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - angle;
- } else if (angle > this.upperLimit) {
- if (this.limitState != 1) {
- this.limitState = 1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.upperLimit - angle;
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- this.limitVelocity = 0;
- }
- if (!enableSpring) {
- if (this.limitVelocity > 0.02) this.limitVelocity -= 0.02;
- else if (this.limitVelocity < -0.02) this.limitVelocity += 0.02;
- else this.limitVelocity = 0;
- }
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- }
- if (this.enableMotor && (this.limitState != 0 || enableSpring)) {
- this.maxMotorImpulse = this.maxMotorForce * timeStep;
- } else {
- this.motorImpulse = 0;
- this.maxMotorImpulse = 0;
- }
- this.a1x = this.ax * this.i1e00 + this.ay * this.i1e01 + this.az * this.i1e02;
- this.a1y = this.ax * this.i1e10 + this.ay * this.i1e11 + this.az * this.i1e12;
- this.a1z = this.ax * this.i1e20 + this.ay * this.i1e21 + this.az * this.i1e22;
- this.a2x = this.ax * this.i2e00 + this.ay * this.i2e01 + this.az * this.i2e02;
- this.a2y = this.ax * this.i2e10 + this.ay * this.i2e11 + this.az * this.i2e12;
- this.a2z = this.ax * this.i2e20 + this.ay * this.i2e21 + this.az * this.i2e22;
- this.motorDenom = this.ax * (this.a1x + this.a2x) + this.ay * (this.a1y + this.a2y) + this.az * (this.a1z + this.a2z);
- this.invMotorDenom = 1 / this.motorDenom;
- if (enableSpring && this.limitState != 2) {
- var omega = 6.2831853 * frequency;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor.dampingRatio * omega);
- this.cfm = this.motorDenom * dmp;
- this.limitVelocity *= k * dmp;
- } else {
- this.cfm = 0;
- this.limitVelocity *= invTimeStep * 0.05;
- }
- this.invDenom = 1 / (this.motorDenom + this.cfm);
- this.limitImpulse *= 0.95;
- this.motorImpulse *= 0.95;
- var totalImpulse = this.limitImpulse + this.motorImpulse;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- },
- solve: function () {
- var rvn = this.ax * (this.a2.x - this.a1.x) + this.ay * (this.a2.y - this.a1.y) + this.az * (this.a2.z - this.a1.z);
- // motor part
- var newMotorImpulse;
- if (this.enableMotor) {
- newMotorImpulse = (rvn - this.motorSpeed) * this.invMotorDenom;
- var oldMotorImpulse = this.motorImpulse;
- this.motorImpulse += newMotorImpulse;
- if (this.motorImpulse > this.maxMotorImpulse) this.motorImpulse = this.maxMotorImpulse;
- else if (this.motorImpulse < -this.maxMotorImpulse) this.motorImpulse = -this.maxMotorImpulse;
- newMotorImpulse = this.motorImpulse - oldMotorImpulse;
- rvn -= newMotorImpulse * this.motorDenom;
- } else newMotorImpulse = 0;
- // limit part
- var newLimitImpulse;
- if (this.limitState != 2) {
- newLimitImpulse = (rvn - this.limitVelocity - this.limitImpulse * this.cfm) * this.invDenom;
- var oldLimitImpulse = this.limitImpulse;
- this.limitImpulse += newLimitImpulse;
- if (this.limitImpulse * this.limitState < 0) this.limitImpulse = 0;
- newLimitImpulse = this.limitImpulse - oldLimitImpulse;
- } else newLimitImpulse = 0;
- var totalImpulse = newLimitImpulse + newMotorImpulse;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- }
- }
- /**
- * A three-axis translational constraint for various joints.
- * @author saharan
- */
- OIMO.Translational3Constraint = function (joint, limitMotor1, limitMotor2, limitMotor3) {
- this.m1 = NaN;
- this.m2 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.ax1 = NaN;
- this.ay1 = NaN;
- this.az1 = NaN;
- this.ax2 = NaN;
- this.ay2 = NaN;
- this.az2 = NaN;
- this.ax3 = NaN;
- this.ay3 = NaN;
- this.az3 = NaN;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.t1x1 = NaN;// jacobians
- this.t1y1 = NaN;
- this.t1z1 = NaN;
- this.t2x1 = NaN;
- this.t2y1 = NaN;
- this.t2z1 = NaN;
- this.l1x1 = NaN;
- this.l1y1 = NaN;
- this.l1z1 = NaN;
- this.l2x1 = NaN;
- this.l2y1 = NaN;
- this.l2z1 = NaN;
- this.a1x1 = NaN;
- this.a1y1 = NaN;
- this.a1z1 = NaN;
- this.a2x1 = NaN;
- this.a2y1 = NaN;
- this.a2z1 = NaN;
- this.t1x2 = NaN;
- this.t1y2 = NaN;
- this.t1z2 = NaN;
- this.t2x2 = NaN;
- this.t2y2 = NaN;
- this.t2z2 = NaN;
- this.l1x2 = NaN;
- this.l1y2 = NaN;
- this.l1z2 = NaN;
- this.l2x2 = NaN;
- this.l2y2 = NaN;
- this.l2z2 = NaN;
- this.a1x2 = NaN;
- this.a1y2 = NaN;
- this.a1z2 = NaN;
- this.a2x2 = NaN;
- this.a2y2 = NaN;
- this.a2z2 = NaN;
- this.t1x3 = NaN;
- this.t1y3 = NaN;
- this.t1z3 = NaN;
- this.t2x3 = NaN;
- this.t2y3 = NaN;
- this.t2z3 = NaN;
- this.l1x3 = NaN;
- this.l1y3 = NaN;
- this.l1z3 = NaN;
- this.l2x3 = NaN;
- this.l2y3 = NaN;
- this.l2z3 = NaN;
- this.a1x3 = NaN;
- this.a1y3 = NaN;
- this.a1z3 = NaN;
- this.a2x3 = NaN;
- this.a2y3 = NaN;
- this.a2z3 = NaN;
- this.lowerLimit1 = NaN;
- this.upperLimit1 = NaN;
- this.limitVelocity1 = NaN;
- this.limitState1 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor1 = false;
- this.motorSpeed1 = NaN;
- this.maxMotorForce1 = NaN;
- this.maxMotorImpulse1 = NaN;
- this.lowerLimit2 = NaN;
- this.upperLimit2 = NaN;
- this.limitVelocity2 = NaN;
- this.limitState2 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor2 = false;
- this.motorSpeed2 = NaN;
- this.maxMotorForce2 = NaN;
- this.maxMotorImpulse2 = NaN;
- this.lowerLimit3 = NaN;
- this.upperLimit3 = NaN;
- this.limitVelocity3 = NaN;
- this.limitState3 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor3 = false;
- this.motorSpeed3 = NaN;
- this.maxMotorForce3 = NaN;
- this.maxMotorImpulse3 = NaN;
- this.k00 = NaN; // K = J*M*JT
- this.k01 = NaN;
- this.k02 = NaN;
- this.k10 = NaN;
- this.k11 = NaN;
- this.k12 = NaN;
- this.k20 = NaN;
- this.k21 = NaN;
- this.k22 = NaN;
- this.kv00 = NaN; // diagonals without CFMs
- this.kv11 = NaN;
- this.kv22 = NaN;
- this.dv00 = NaN; // ...inverted
- this.dv11 = NaN;
- this.dv22 = NaN;
- this.d00 = NaN; // K^-1
- this.d01 = NaN;
- this.d02 = NaN;
- this.d10 = NaN;
- this.d11 = NaN;
- this.d12 = NaN;
- this.d20 = NaN;
- this.d21 = NaN;
- this.d22 = NaN;
- this.limitMotor1 = limitMotor1;
- this.limitMotor2 = limitMotor2;
- this.limitMotor3 = limitMotor3;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse1 = 0;
- this.motorImpulse1 = 0;
- this.limitImpulse2 = 0;
- this.motorImpulse2 = 0;
- this.limitImpulse3 = 0;
- this.motorImpulse3 = 0;
- this.cfm1 = 0;// Constraint Force Mixing
- this.cfm2 = 0;
- this.cfm3 = 0;
- this.weight = -1;
- }
- OIMO.Translational3Constraint.prototype = {
- constructor: OIMO.Translational3Constraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax1 = this.limitMotor1.axis.x;
- this.ay1 = this.limitMotor1.axis.y;
- this.az1 = this.limitMotor1.axis.z;
- this.ax2 = this.limitMotor2.axis.x;
- this.ay2 = this.limitMotor2.axis.y;
- this.az2 = this.limitMotor2.axis.z;
- this.ax3 = this.limitMotor3.axis.x;
- this.ay3 = this.limitMotor3.axis.y;
- this.az3 = this.limitMotor3.axis.z;
- this.lowerLimit1 = this.limitMotor1.lowerLimit;
- this.upperLimit1 = this.limitMotor1.upperLimit;
- this.motorSpeed1 = this.limitMotor1.motorSpeed;
- this.maxMotorForce1 = this.limitMotor1.maxMotorForce;
- this.enableMotor1 = this.maxMotorForce1 > 0;
- this.lowerLimit2 = this.limitMotor2.lowerLimit;
- this.upperLimit2 = this.limitMotor2.upperLimit;
- this.motorSpeed2 = this.limitMotor2.motorSpeed;
- this.maxMotorForce2 = this.limitMotor2.maxMotorForce;
- this.enableMotor2 = this.maxMotorForce2 > 0;
- this.lowerLimit3 = this.limitMotor3.lowerLimit;
- this.upperLimit3 = this.limitMotor3.upperLimit;
- this.motorSpeed3 = this.limitMotor3.motorSpeed;
- this.maxMotorForce3 = this.limitMotor3.maxMotorForce;
- this.enableMotor3 = this.maxMotorForce3 > 0;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var dx = this.p2.x - this.p1.x;
- var dy = this.p2.y - this.p1.y;
- var dz = this.p2.z - this.p1.z;
- var d1 = dx * this.ax1 + dy * this.ay1 + dz * this.az1;
- var d2 = dx * this.ax2 + dy * this.ay2 + dz * this.az2;
- var d3 = dx * this.ax3 + dy * this.ay3 + dz * this.az3;
- var frequency1 = this.limitMotor1.frequency;
- var frequency2 = this.limitMotor2.frequency;
- var frequency3 = this.limitMotor3.frequency;
- var enableSpring1 = frequency1 > 0;
- var enableSpring2 = frequency2 > 0;
- var enableSpring3 = frequency3 > 0;
- var enableLimit1 = this.lowerLimit1 <= this.upperLimit1;
- var enableLimit2 = this.lowerLimit2 <= this.upperLimit2;
- var enableLimit3 = this.lowerLimit3 <= this.upperLimit3;
- // for stability
- if (enableSpring1 && d1 > 20 || d1 < -20) {
- enableSpring1 = false;
- }
- if (enableSpring2 && d2 > 20 || d2 < -20) {
- enableSpring2 = false;
- }
- if (enableSpring3 && d3 > 20 || d3 < -20) {
- enableSpring3 = false;
- }
- if (enableLimit1) {
- if (this.lowerLimit1 == this.upperLimit1) {
- if (this.limitState1 != 0) {
- this.limitState1 = 0;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - d1;
- if (!enableSpring1) d1 = this.lowerLimit1;
- } else if (d1 < this.lowerLimit1) {
- if (this.limitState1 != -1) {
- this.limitState1 = -1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - d1;
- if (!enableSpring1) d1 = this.lowerLimit1;
- } else if (d1 > this.upperLimit1) {
- if (this.limitState1 != 1) {
- this.limitState1 = 1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.upperLimit1 - d1;
- if (!enableSpring1) d1 = this.upperLimit1;
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- this.limitVelocity1 = 0;
- }
- if (!enableSpring1) {
- if (this.limitVelocity1 > 0.005) this.limitVelocity1 -= 0.005;
- else if (this.limitVelocity1 < -0.005) this.limitVelocity1 += 0.005;
- else this.limitVelocity1 = 0;
- }
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- }
- if (enableLimit2) {
- if (this.lowerLimit2 == this.upperLimit2) {
- if (this.limitState2 != 0) {
- this.limitState2 = 0;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - d2;
- if (!enableSpring2) d2 = this.lowerLimit2;
- } else if (d2 < this.lowerLimit2) {
- if (this.limitState2 != -1) {
- this.limitState2 = -1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - d2;
- if (!enableSpring2) d2 = this.lowerLimit2;
- } else if (d2 > this.upperLimit2) {
- if (this.limitState2 != 1) {
- this.limitState2 = 1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.upperLimit2 - d2;
- if (!enableSpring2) d2 = this.upperLimit2;
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- this.limitVelocity2 = 0;
- }
- if (!enableSpring2) {
- if (this.limitVelocity2 > 0.005) this.limitVelocity2 -= 0.005;
- else if (this.limitVelocity2 < -0.005) this.limitVelocity2 += 0.005;
- else this.limitVelocity2 = 0;
- }
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- }
- if (enableLimit3) {
- if (this.lowerLimit3 == this.upperLimit3) {
- if (this.limitState3 != 0) {
- this.limitState3 = 0;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - d3;
- if (!enableSpring3) d3 = this.lowerLimit3;
- } else if (d3 < this.lowerLimit3) {
- if (this.limitState3 != -1) {
- this.limitState3 = -1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - d3;
- if (!enableSpring3) d3 = this.lowerLimit3;
- } else if (d3 > this.upperLimit3) {
- if (this.limitState3 != 1) {
- this.limitState3 = 1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.upperLimit3 - d3;
- if (!enableSpring3) d3 = this.upperLimit3;
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- this.limitVelocity3 = 0;
- }
- if (!enableSpring3) {
- if (this.limitVelocity3 > 0.005) this.limitVelocity3 -= 0.005;
- else if (this.limitVelocity3 < -0.005) this.limitVelocity3 += 0.005;
- else this.limitVelocity3 = 0;
- }
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- }
- if (this.enableMotor1 && (this.limitState1 != 0 || enableSpring1)) {
- this.maxMotorImpulse1 = this.maxMotorForce1 * timeStep;
- } else {
- this.motorImpulse1 = 0;
- this.maxMotorImpulse1 = 0;
- }
- if (this.enableMotor2 && (this.limitState2 != 0 || enableSpring2)) {
- this.maxMotorImpulse2 = this.maxMotorForce2 * timeStep;
- } else {
- this.motorImpulse2 = 0;
- this.maxMotorImpulse2 = 0;
- }
- if (this.enableMotor3 && (this.limitState3 != 0 || enableSpring3)) {
- this.maxMotorImpulse3 = this.maxMotorForce3 * timeStep;
- } else {
- this.motorImpulse3 = 0;
- this.maxMotorImpulse3 = 0;
- }
- var rdx = d1 * this.ax1 + d2 * this.ax2 + d3 * this.ax2;
- var rdy = d1 * this.ay1 + d2 * this.ay2 + d3 * this.ay2;
- var rdz = d1 * this.az1 + d2 * this.az2 + d3 * this.az2;
- var w1 = this.m2 / (this.m1 + this.m2);
- if (this.weight >= 0) w1 = this.weight; // use given weight
- var w2 = 1 - w1;
- this.r1x = this.r1.x + rdx * w1;
- this.r1y = this.r1.y + rdy * w1;
- this.r1z = this.r1.z + rdz * w1;
- this.r2x = this.r2.x - rdx * w2;
- this.r2y = this.r2.y - rdy * w2;
- this.r2z = this.r2.z - rdz * w2;
- // build jacobians
- this.t1x1 = this.r1y * this.az1 - this.r1z * this.ay1;
- this.t1y1 = this.r1z * this.ax1 - this.r1x * this.az1;
- this.t1z1 = this.r1x * this.ay1 - this.r1y * this.ax1;
- this.t2x1 = this.r2y * this.az1 - this.r2z * this.ay1;
- this.t2y1 = this.r2z * this.ax1 - this.r2x * this.az1;
- this.t2z1 = this.r2x * this.ay1 - this.r2y * this.ax1;
- this.l1x1 = this.ax1 * this.m1;
- this.l1y1 = this.ay1 * this.m1;
- this.l1z1 = this.az1 * this.m1;
- this.l2x1 = this.ax1 * this.m2;
- this.l2y1 = this.ay1 * this.m2;
- this.l2z1 = this.az1 * this.m2;
- this.a1x1 = this.t1x1 * this.i1e00 + this.t1y1 * this.i1e01 + this.t1z1 * this.i1e02;
- this.a1y1 = this.t1x1 * this.i1e10 + this.t1y1 * this.i1e11 + this.t1z1 * this.i1e12;
- this.a1z1 = this.t1x1 * this.i1e20 + this.t1y1 * this.i1e21 + this.t1z1 * this.i1e22;
- this.a2x1 = this.t2x1 * this.i2e00 + this.t2y1 * this.i2e01 + this.t2z1 * this.i2e02;
- this.a2y1 = this.t2x1 * this.i2e10 + this.t2y1 * this.i2e11 + this.t2z1 * this.i2e12;
- this.a2z1 = this.t2x1 * this.i2e20 + this.t2y1 * this.i2e21 + this.t2z1 * this.i2e22;
- this.t1x2 = this.r1y * this.az2 - this.r1z * this.ay2;
- this.t1y2 = this.r1z * this.ax2 - this.r1x * this.az2;
- this.t1z2 = this.r1x * this.ay2 - this.r1y * this.ax2;
- this.t2x2 = this.r2y * this.az2 - this.r2z * this.ay2;
- this.t2y2 = this.r2z * this.ax2 - this.r2x * this.az2;
- this.t2z2 = this.r2x * this.ay2 - this.r2y * this.ax2;
- this.l1x2 = this.ax2 * this.m1;
- this.l1y2 = this.ay2 * this.m1;
- this.l1z2 = this.az2 * this.m1;
- this.l2x2 = this.ax2 * this.m2;
- this.l2y2 = this.ay2 * this.m2;
- this.l2z2 = this.az2 * this.m2;
- this.a1x2 = this.t1x2 * this.i1e00 + this.t1y2 * this.i1e01 + this.t1z2 * this.i1e02;
- this.a1y2 = this.t1x2 * this.i1e10 + this.t1y2 * this.i1e11 + this.t1z2 * this.i1e12;
- this.a1z2 = this.t1x2 * this.i1e20 + this.t1y2 * this.i1e21 + this.t1z2 * this.i1e22;
- this.a2x2 = this.t2x2 * this.i2e00 + this.t2y2 * this.i2e01 + this.t2z2 * this.i2e02;
- this.a2y2 = this.t2x2 * this.i2e10 + this.t2y2 * this.i2e11 + this.t2z2 * this.i2e12;
- this.a2z2 = this.t2x2 * this.i2e20 + this.t2y2 * this.i2e21 + this.t2z2 * this.i2e22;
- this.t1x3 = this.r1y * this.az3 - this.r1z * this.ay3;
- this.t1y3 = this.r1z * this.ax3 - this.r1x * this.az3;
- this.t1z3 = this.r1x * this.ay3 - this.r1y * this.ax3;
- this.t2x3 = this.r2y * this.az3 - this.r2z * this.ay3;
- this.t2y3 = this.r2z * this.ax3 - this.r2x * this.az3;
- this.t2z3 = this.r2x * this.ay3 - this.r2y * this.ax3;
- this.l1x3 = this.ax3 * this.m1;
- this.l1y3 = this.ay3 * this.m1;
- this.l1z3 = this.az3 * this.m1;
- this.l2x3 = this.ax3 * this.m2;
- this.l2y3 = this.ay3 * this.m2;
- this.l2z3 = this.az3 * this.m2;
- this.a1x3 = this.t1x3 * this.i1e00 + this.t1y3 * this.i1e01 + this.t1z3 * this.i1e02;
- this.a1y3 = this.t1x3 * this.i1e10 + this.t1y3 * this.i1e11 + this.t1z3 * this.i1e12;
- this.a1z3 = this.t1x3 * this.i1e20 + this.t1y3 * this.i1e21 + this.t1z3 * this.i1e22;
- this.a2x3 = this.t2x3 * this.i2e00 + this.t2y3 * this.i2e01 + this.t2z3 * this.i2e02;
- this.a2y3 = this.t2x3 * this.i2e10 + this.t2y3 * this.i2e11 + this.t2z3 * this.i2e12;
- this.a2z3 = this.t2x3 * this.i2e20 + this.t2y3 * this.i2e21 + this.t2z3 * this.i2e22;
- // build an impulse matrix
- var m12 = this.m1 + this.m2;
- this.k00 = (this.ax1 * this.ax1 + this.ay1 * this.ay1 + this.az1 * this.az1) * m12;
- this.k01 = (this.ax1 * this.ax2 + this.ay1 * this.ay2 + this.az1 * this.az2) * m12;
- this.k02 = (this.ax1 * this.ax3 + this.ay1 * this.ay3 + this.az1 * this.az3) * m12;
- this.k10 = (this.ax2 * this.ax1 + this.ay2 * this.ay1 + this.az2 * this.az1) * m12;
- this.k11 = (this.ax2 * this.ax2 + this.ay2 * this.ay2 + this.az2 * this.az2) * m12;
- this.k12 = (this.ax2 * this.ax3 + this.ay2 * this.ay3 + this.az2 * this.az3) * m12;
- this.k20 = (this.ax3 * this.ax1 + this.ay3 * this.ay1 + this.az3 * this.az1) * m12;
- this.k21 = (this.ax3 * this.ax2 + this.ay3 * this.ay2 + this.az3 * this.az2) * m12;
- this.k22 = (this.ax3 * this.ax3 + this.ay3 * this.ay3 + this.az3 * this.az3) * m12;
- this.k00 += this.t1x1 * this.a1x1 + this.t1y1 * this.a1y1 + this.t1z1 * this.a1z1;
- this.k01 += this.t1x1 * this.a1x2 + this.t1y1 * this.a1y2 + this.t1z1 * this.a1z2;
- this.k02 += this.t1x1 * this.a1x3 + this.t1y1 * this.a1y3 + this.t1z1 * this.a1z3;
- this.k10 += this.t1x2 * this.a1x1 + this.t1y2 * this.a1y1 + this.t1z2 * this.a1z1;
- this.k11 += this.t1x2 * this.a1x2 + this.t1y2 * this.a1y2 + this.t1z2 * this.a1z2;
- this.k12 += this.t1x2 * this.a1x3 + this.t1y2 * this.a1y3 + this.t1z2 * this.a1z3;
- this.k20 += this.t1x3 * this.a1x1 + this.t1y3 * this.a1y1 + this.t1z3 * this.a1z1;
- this.k21 += this.t1x3 * this.a1x2 + this.t1y3 * this.a1y2 + this.t1z3 * this.a1z2;
- this.k22 += this.t1x3 * this.a1x3 + this.t1y3 * this.a1y3 + this.t1z3 * this.a1z3;
- this.k00 += this.t2x1 * this.a2x1 + this.t2y1 * this.a2y1 + this.t2z1 * this.a2z1;
- this.k01 += this.t2x1 * this.a2x2 + this.t2y1 * this.a2y2 + this.t2z1 * this.a2z2;
- this.k02 += this.t2x1 * this.a2x3 + this.t2y1 * this.a2y3 + this.t2z1 * this.a2z3;
- this.k10 += this.t2x2 * this.a2x1 + this.t2y2 * this.a2y1 + this.t2z2 * this.a2z1;
- this.k11 += this.t2x2 * this.a2x2 + this.t2y2 * this.a2y2 + this.t2z2 * this.a2z2;
- this.k12 += this.t2x2 * this.a2x3 + this.t2y2 * this.a2y3 + this.t2z2 * this.a2z3;
- this.k20 += this.t2x3 * this.a2x1 + this.t2y3 * this.a2y1 + this.t2z3 * this.a2z1;
- this.k21 += this.t2x3 * this.a2x2 + this.t2y3 * this.a2y2 + this.t2z3 * this.a2z2;
- this.k22 += this.t2x3 * this.a2x3 + this.t2y3 * this.a2y3 + this.t2z3 * this.a2z3;
- this.kv00 = this.k00;
- this.kv11 = this.k11;
- this.kv22 = this.k22;
- this.dv00 = 1 / this.kv00;
- this.dv11 = 1 / this.kv11;
- this.dv22 = 1 / this.kv22;
- if (enableSpring1 && this.limitState1 != 2) {
- var omega = 6.2831853 * frequency1;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor1.dampingRatio * omega);
- this.cfm1 = this.kv00 * dmp;
- this.limitVelocity1 *= k * dmp;
- } else {
- this.cfm1 = 0;
- this.limitVelocity1 *= invTimeStep * 0.05;
- }
- if (enableSpring2 && this.limitState2 != 2) {
- omega = 6.2831853 * frequency2;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor2.dampingRatio * omega);
- this.cfm2 = this.kv11 * dmp;
- this.limitVelocity2 *= k * dmp;
- } else {
- this.cfm2 = 0;
- this.limitVelocity2 *= invTimeStep * 0.05;
- }
- if (enableSpring3 && this.limitState3 != 2) {
- omega = 6.2831853 * frequency3;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor3.dampingRatio * omega);
- this.cfm3 = this.kv22 * dmp;
- this.limitVelocity3 *= k * dmp;
- } else {
- this.cfm3 = 0;
- this.limitVelocity3 *= invTimeStep * 0.05;
- }
- this.k00 += this.cfm1;
- this.k11 += this.cfm2;
- this.k22 += this.cfm3;
- var inv = 1 / (
- this.k00 * (this.k11 * this.k22 - this.k21 * this.k12) +
- this.k10 * (this.k21 * this.k02 - this.k01 * this.k22) +
- this.k20 * (this.k01 * this.k12 - this.k11 * this.k02)
- );
- this.d00 = (this.k11 * this.k22 - this.k12 * this.k21) * inv;
- this.d01 = (this.k02 * this.k21 - this.k01 * this.k22) * inv;
- this.d02 = (this.k01 * this.k12 - this.k02 * this.k11) * inv;
- this.d10 = (this.k12 * this.k20 - this.k10 * this.k22) * inv;
- this.d11 = (this.k00 * this.k22 - this.k02 * this.k20) * inv;
- this.d12 = (this.k02 * this.k10 - this.k00 * this.k12) * inv;
- this.d20 = (this.k10 * this.k21 - this.k11 * this.k20) * inv;
- this.d21 = (this.k01 * this.k20 - this.k00 * this.k21) * inv;
- this.d22 = (this.k00 * this.k11 - this.k01 * this.k10) * inv;
- // warm starting
- var totalImpulse1 = this.limitImpulse1 + this.motorImpulse1;
- var totalImpulse2 = this.limitImpulse2 + this.motorImpulse2;
- var totalImpulse3 = this.limitImpulse3 + this.motorImpulse3;
- this.l1.x += totalImpulse1 * this.l1x1 + totalImpulse2 * this.l1x2 + totalImpulse3 * this.l1x3;
- this.l1.y += totalImpulse1 * this.l1y1 + totalImpulse2 * this.l1y2 + totalImpulse3 * this.l1y3;
- this.l1.z += totalImpulse1 * this.l1z1 + totalImpulse2 * this.l1z2 + totalImpulse3 * this.l1z3;
- this.a1.x += totalImpulse1 * this.a1x1 + totalImpulse2 * this.a1x2 + totalImpulse3 * this.a1x3;
- this.a1.y += totalImpulse1 * this.a1y1 + totalImpulse2 * this.a1y2 + totalImpulse3 * this.a1y3;
- this.a1.z += totalImpulse1 * this.a1z1 + totalImpulse2 * this.a1z2 + totalImpulse3 * this.a1z3;
- this.l2.x -= totalImpulse1 * this.l2x1 + totalImpulse2 * this.l2x2 + totalImpulse3 * this.l2x3;
- this.l2.y -= totalImpulse1 * this.l2y1 + totalImpulse2 * this.l2y2 + totalImpulse3 * this.l2y3;
- this.l2.z -= totalImpulse1 * this.l2z1 + totalImpulse2 * this.l2z2 + totalImpulse3 * this.l2z3;
- this.a2.x -= totalImpulse1 * this.a2x1 + totalImpulse2 * this.a2x2 + totalImpulse3 * this.a2x3;
- this.a2.y -= totalImpulse1 * this.a2y1 + totalImpulse2 * this.a2y2 + totalImpulse3 * this.a2y3;
- this.a2.z -= totalImpulse1 * this.a2z1 + totalImpulse2 * this.a2z2 + totalImpulse3 * this.a2z3;
- },
- solve: function () {
- var rvx = this.l2.x - this.l1.x + this.a2.y * this.r2z - this.a2.z * this.r2y - this.a1.y * this.r1z + this.a1.z * this.r1y;
- var rvy = this.l2.y - this.l1.y + this.a2.z * this.r2x - this.a2.x * this.r2z - this.a1.z * this.r1x + this.a1.x * this.r1z;
- var rvz = this.l2.z - this.l1.z + this.a2.x * this.r2y - this.a2.y * this.r2x - this.a1.x * this.r1y + this.a1.y * this.r1x;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3;
- var oldMotorImpulse1 = this.motorImpulse1;
- var oldMotorImpulse2 = this.motorImpulse2;
- var oldMotorImpulse3 = this.motorImpulse3;
- var dMotorImpulse1 = 0;
- var dMotorImpulse2 = 0;
- var dMotorImpulse3 = 0;
- if (this.enableMotor1) {
- dMotorImpulse1 = (rvn1 - this.motorSpeed1) * this.dv00;
- this.motorImpulse1 += dMotorImpulse1;
- if (this.motorImpulse1 > this.maxMotorImpulse1) { // clamp motor impulse
- this.motorImpulse1 = this.maxMotorImpulse1;
- } else if (this.motorImpulse1 < -this.maxMotorImpulse1) {
- this.motorImpulse1 = -this.maxMotorImpulse1;
- }
- dMotorImpulse1 = this.motorImpulse1 - oldMotorImpulse1;
- }
- if (this.enableMotor2) {
- dMotorImpulse2 = (rvn2 - this.motorSpeed2) * this.dv11;
- this.motorImpulse2 += dMotorImpulse2;
- if (this.motorImpulse2 > this.maxMotorImpulse2) { // clamp motor impulse
- this.motorImpulse2 = this.maxMotorImpulse2;
- } else if (this.motorImpulse2 < -this.maxMotorImpulse2) {
- this.motorImpulse2 = -this.maxMotorImpulse2;
- }
- dMotorImpulse2 = this.motorImpulse2 - oldMotorImpulse2;
- }
- if (this.enableMotor3) {
- dMotorImpulse3 = (rvn3 - this.motorSpeed3) * this.dv22;
- this.motorImpulse3 += dMotorImpulse3;
- if (this.motorImpulse3 > this.maxMotorImpulse3) { // clamp motor impulse
- this.motorImpulse3 = this.maxMotorImpulse3;
- } else if (this.motorImpulse3 < -this.maxMotorImpulse3) {
- this.motorImpulse3 = -this.maxMotorImpulse3;
- }
- dMotorImpulse3 = this.motorImpulse3 - oldMotorImpulse3;
- }
- // apply motor impulse to relative velocity
- rvn1 += dMotorImpulse1 * this.kv00 + dMotorImpulse2 * this.k01 + dMotorImpulse3 * this.k02;
- rvn2 += dMotorImpulse1 * this.k10 + dMotorImpulse2 * this.kv11 + dMotorImpulse3 * this.k12;
- rvn3 += dMotorImpulse1 * this.k20 + dMotorImpulse2 * this.k21 + dMotorImpulse3 * this.kv22;
- // subtract target velocity and applied impulse
- rvn1 -= this.limitVelocity1 + this.limitImpulse1 * this.cfm1;
- rvn2 -= this.limitVelocity2 + this.limitImpulse2 * this.cfm2;
- rvn3 -= this.limitVelocity3 + this.limitImpulse3 * this.cfm3;
- var oldLimitImpulse1 = this.limitImpulse1;
- var oldLimitImpulse2 = this.limitImpulse2;
- var oldLimitImpulse3 = this.limitImpulse3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- // clamp
- var clampState = 0;
- if (this.limitState1 == 2 || this.limitImpulse1 * this.limitState1 < 0) {
- dLimitImpulse1 = -oldLimitImpulse1;
- rvn2 += dLimitImpulse1 * this.k10;
- rvn3 += dLimitImpulse1 * this.k20;
- clampState |= 1;
- }
- if (this.limitState2 == 2 || this.limitImpulse2 * this.limitState2 < 0) {
- dLimitImpulse2 = -oldLimitImpulse2;
- rvn1 += dLimitImpulse2 * this.k01;
- rvn3 += dLimitImpulse2 * this.k21;
- clampState |= 2;
- }
- if (this.limitState3 == 2 || this.limitImpulse3 * this.limitState3 < 0) {
- dLimitImpulse3 = -oldLimitImpulse3;
- rvn1 += dLimitImpulse3 * this.k02;
- rvn2 += dLimitImpulse3 * this.k12;
- clampState |= 4;
- }
- // update un-clamped impulse
- // TODO: isolate division
- var det;
- switch (clampState) {
- case 1:// update 2 3
- det = 1 / (this.k11 * this.k22 - this.k12 * this.k21);
- dLimitImpulse2 = (this.k22 * rvn2 + -this.k12 * rvn3) * det;
- dLimitImpulse3 = (-this.k21 * rvn2 + this.k11 * rvn3) * det;
- break;
- case 2:// update 1 3
- det = 1 / (this.k00 * this.k22 - this.k02 * this.k20);
- dLimitImpulse1 = (this.k22 * rvn1 + -this.k02 * rvn3) * det;
- dLimitImpulse3 = (-this.k20 * rvn1 + this.k00 * rvn3) * det;
- break;
- case 3:// update 3
- dLimitImpulse3 = rvn3 / this.k22;
- break;
- case 4:// update 1 2
- det = 1 / (this.k00 * this.k11 - this.k01 * this.k10);
- dLimitImpulse1 = (this.k11 * rvn1 + -this.k01 * rvn2) * det;
- dLimitImpulse2 = (-this.k10 * rvn1 + this.k00 * rvn2) * det;
- break;
- case 5:// update 2
- dLimitImpulse2 = rvn2 / this.k11;
- break;
- case 6:// update 1
- dLimitImpulse1 = rvn1 / this.k00;
- break;
- }
- this.limitImpulse1 = oldLimitImpulse1 + dLimitImpulse1;
- this.limitImpulse2 = oldLimitImpulse2 + dLimitImpulse2;
- this.limitImpulse3 = oldLimitImpulse3 + dLimitImpulse3;
- var dImpulse1 = dMotorImpulse1 + dLimitImpulse1;
- var dImpulse2 = dMotorImpulse2 + dLimitImpulse2;
- var dImpulse3 = dMotorImpulse3 + dLimitImpulse3;
- // apply impulse
- this.l1.x += dImpulse1 * this.l1x1 + dImpulse2 * this.l1x2 + dImpulse3 * this.l1x3;
- this.l1.y += dImpulse1 * this.l1y1 + dImpulse2 * this.l1y2 + dImpulse3 * this.l1y3;
- this.l1.z += dImpulse1 * this.l1z1 + dImpulse2 * this.l1z2 + dImpulse3 * this.l1z3;
- this.a1.x += dImpulse1 * this.a1x1 + dImpulse2 * this.a1x2 + dImpulse3 * this.a1x3;
- this.a1.y += dImpulse1 * this.a1y1 + dImpulse2 * this.a1y2 + dImpulse3 * this.a1y3;
- this.a1.z += dImpulse1 * this.a1z1 + dImpulse2 * this.a1z2 + dImpulse3 * this.a1z3;
- this.l2.x -= dImpulse1 * this.l2x1 + dImpulse2 * this.l2x2 + dImpulse3 * this.l2x3;
- this.l2.y -= dImpulse1 * this.l2y1 + dImpulse2 * this.l2y2 + dImpulse3 * this.l2y3;
- this.l2.z -= dImpulse1 * this.l2z1 + dImpulse2 * this.l2z2 + dImpulse3 * this.l2z3;
- this.a2.x -= dImpulse1 * this.a2x1 + dImpulse2 * this.a2x2 + dImpulse3 * this.a2x3;
- this.a2.y -= dImpulse1 * this.a2y1 + dImpulse2 * this.a2y2 + dImpulse3 * this.a2y3;
- this.a2.z -= dImpulse1 * this.a2z1 + dImpulse2 * this.a2z2 + dImpulse3 * this.a2z3;
- }
- }
- /**
- * A translational constraint for various joints.
- * @author saharan
- */
- OIMO.TranslationalConstraint = function (joint, limitMotor) {
- this.cfm = NaN;
- this.m1 = NaN;
- this.m2 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.motorDenom = NaN;
- this.invMotorDenom = NaN;
- this.invDenom = NaN;
- this.ax = NaN;
- this.ay = NaN;
- this.az = NaN;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.t1x = NaN;
- this.t1y = NaN;
- this.t1z = NaN;
- this.t2x = NaN;
- this.t2y = NaN;
- this.t2z = NaN;
- this.l1x = NaN;
- this.l1y = NaN;
- this.l1z = NaN;
- this.l2x = NaN;
- this.l2y = NaN;
- this.l2z = NaN;
- this.a1x = NaN;
- this.a1y = NaN;
- this.a1z = NaN;
- this.a2x = NaN;
- this.a2y = NaN;
- this.a2z = NaN;
- this.lowerLimit = NaN;
- this.upperLimit = NaN;
- this.limitVelocity = NaN;
- this.limitState = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor = false;
- this.motorSpeed = NaN;
- this.maxMotorForce = NaN;
- this.maxMotorImpulse = NaN;
- this.limitMotor = limitMotor;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse = 0;
- this.motorImpulse = 0;
- }
- OIMO.TranslationalConstraint.prototype = {
- constructor: OIMO.TranslationalConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax = this.limitMotor.axis.x;
- this.ay = this.limitMotor.axis.y;
- this.az = this.limitMotor.axis.z;
- this.lowerLimit = this.limitMotor.lowerLimit;
- this.upperLimit = this.limitMotor.upperLimit;
- this.motorSpeed = this.limitMotor.motorSpeed;
- this.maxMotorForce = this.limitMotor.maxMotorForce;
- this.enableMotor = this.maxMotorForce > 0;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var dx = this.p2.x - this.p1.x;
- var dy = this.p2.y - this.p1.y;
- var dz = this.p2.z - this.p1.z;
- var d = dx * this.ax + dy * this.ay + dz * this.az;
- var frequency = this.limitMotor.frequency;
- var enableSpring = frequency > 0;
- var enableLimit = this.lowerLimit <= this.upperLimit;
- if (enableSpring && d > 20 || d < -20) {
- enableSpring = false;
- }
- if (enableLimit) {
- if (this.lowerLimit == this.upperLimit) {
- if (this.limitState != 0) {
- this.limitState = 0;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - d;
- if (!enableSpring) d = this.lowerLimit;
- } else if (d < this.lowerLimit) {
- if (this.limitState != -1) {
- this.limitState = -1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - d;
- if (!enableSpring) d = this.lowerLimit;
- } else if (d > this.upperLimit) {
- if (this.limitState != 1) {
- this.limitState = 1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.upperLimit - d;
- if (!enableSpring) d = this.upperLimit;
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- this.limitVelocity = 0;
- }
- if (!enableSpring) {
- if (this.limitVelocity > 0.005) this.limitVelocity -= 0.005;
- else if (this.limitVelocity < -0.005) this.limitVelocity += 0.005;
- else this.limitVelocity = 0;
- }
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- }
- if (this.enableMotor && (this.limitState != 0 || enableSpring)) {
- this.maxMotorImpulse = this.maxMotorForce * timeStep;
- } else {
- this.motorImpulse = 0;
- this.maxMotorImpulse = 0;
- }
- var rdx = d * this.ax;
- var rdy = d * this.ay;
- var rdz = d * this.az;
- var w1 = this.m1 / (this.m1 + this.m2);
- var w2 = 1 - w1;
- this.r1x = this.r1.x + rdx * w1;
- this.r1y = this.r1.y + rdy * w1;
- this.r1z = this.r1.z + rdz * w1;
- this.r2x = this.r2.x - rdx * w2;
- this.r2y = this.r2.y - rdy * w2;
- this.r2z = this.r2.z - rdz * w2;
- this.t1x = this.r1y * this.az - this.r1z * this.ay;
- this.t1y = this.r1z * this.ax - this.r1x * this.az;
- this.t1z = this.r1x * this.ay - this.r1y * this.ax;
- this.t2x = this.r2y * this.az - this.r2z * this.ay;
- this.t2y = this.r2z * this.ax - this.r2x * this.az;
- this.t2z = this.r2x * this.ay - this.r2y * this.ax;
- this.l1x = this.ax * this.m1;
- this.l1y = this.ay * this.m1;
- this.l1z = this.az * this.m1;
- this.l2x = this.ax * this.m2;
- this.l2y = this.ay * this.m2;
- this.l2z = this.az * this.m2;
- this.a1x = this.t1x * this.i1e00 + this.t1y * this.i1e01 + this.t1z * this.i1e02;
- this.a1y = this.t1x * this.i1e10 + this.t1y * this.i1e11 + this.t1z * this.i1e12;
- this.a1z = this.t1x * this.i1e20 + this.t1y * this.i1e21 + this.t1z * this.i1e22;
- this.a2x = this.t2x * this.i2e00 + this.t2y * this.i2e01 + this.t2z * this.i2e02;
- this.a2y = this.t2x * this.i2e10 + this.t2y * this.i2e11 + this.t2z * this.i2e12;
- this.a2z = this.t2x * this.i2e20 + this.t2y * this.i2e21 + this.t2z * this.i2e22;
- this.motorDenom =
- this.m1 + this.m2 +
- this.ax * (this.a1y * this.r1z - this.a1z * this.r1y + this.a2y * this.r2z - this.a2z * this.r2y) +
- this.ay * (this.a1z * this.r1x - this.a1x * this.r1z + this.a2z * this.r2x - this.a2x * this.r2z) +
- this.az * (this.a1x * this.r1y - this.a1y * this.r1x + this.a2x * this.r2y - this.a2y * this.r2x);
- this.invMotorDenom = 1 / this.motorDenom;
- if (enableSpring && this.limitState != 2) {
- var omega = 6.2831853 * frequency;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor.dampingRatio * omega);
- this.cfm = this.motorDenom * dmp;
- this.limitVelocity *= k * dmp;
- } else {
- this.cfm = 0;
- this.limitVelocity *= invTimeStep * 0.05;
- }
- this.invDenom = 1 / (this.motorDenom + this.cfm);
- var totalImpulse = this.limitImpulse + this.motorImpulse;
- this.l1.x += totalImpulse * this.l1x;
- this.l1.y += totalImpulse * this.l1y;
- this.l1.z += totalImpulse * this.l1z;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.l2.x -= totalImpulse * this.l2x;
- this.l2.y -= totalImpulse * this.l2y;
- this.l2.z -= totalImpulse * this.l2z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- },
- solve: function () {
- var rvn =
- this.ax * (this.l2.x - this.l1.x) + this.ay * (this.l2.y - this.l1.y) + this.az * (this.l2.z - this.l1.z) +
- this.t2x * this.a2.x - this.t1x * this.a1.x + this.t2y * this.a2.y - this.t1y * this.a1.y + this.t2z * this.a2.z - this.t1z * this.a1.z;
- // motor part
- var newMotorImpulse;
- if (this.enableMotor) {
- newMotorImpulse = (rvn - this.motorSpeed) * this.invMotorDenom;
- var oldMotorImpulse = this.motorImpulse;
- this.motorImpulse += newMotorImpulse;
- if (this.motorImpulse > this.maxMotorImpulse) this.motorImpulse = this.maxMotorImpulse;
- else if (this.motorImpulse < -this.maxMotorImpulse) this.motorImpulse = -this.maxMotorImpulse;
- newMotorImpulse = this.motorImpulse - oldMotorImpulse;
- rvn -= newMotorImpulse * this.motorDenom;
- } else newMotorImpulse = 0;
- // limit part
- var newLimitImpulse;
- if (this.limitState != 2) {
- newLimitImpulse = (rvn - this.limitVelocity - this.limitImpulse * this.cfm) * this.invDenom;
- var oldLimitImpulse = this.limitImpulse;
- this.limitImpulse += newLimitImpulse;
- if (this.limitImpulse * this.limitState < 0) this.limitImpulse = 0;
- newLimitImpulse = this.limitImpulse - oldLimitImpulse;
- } else newLimitImpulse = 0;
- var totalImpulse = newLimitImpulse + newMotorImpulse;
- this.l1.x += totalImpulse * this.l1x;
- this.l1.y += totalImpulse * this.l1y;
- this.l1.z += totalImpulse * this.l1z;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.l2.x -= totalImpulse * this.l2x;
- this.l2.y -= totalImpulse * this.l2y;
- this.l2.z -= totalImpulse * this.l2z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- }
- }
- /**
- * A contact is a pair of shapes whose axis-aligned bounding boxes are overlapping.
- * @author saharan
- */
- OIMO.Contact = function () {
- // The first shape.
- this.shape1 = null;
- // The second shape.
- this.shape2 = null;
- // The first rigid body.
- this.body1 = null;
- // The second rigid body.
- this.body2 = null;
- // The previous contact in the world.
- this.prev = null;
- // The next contact in the world.
- this.next = null;
- // Internal
- this.persisting = false;
- // Whether both the rigid bodies are sleeping or not.
- this.sleeping = false;
- // The collision detector between two shapes.
- this.detector = null;
- // The contact constraint of the contact.
- this.constraint = null;
- // Whether the shapes are touching or not.
- this.touching = false;
- this.b1Link = new OIMO.ContactLink(this);
- this.b2Link = new OIMO.ContactLink(this);
- this.s1Link = new OIMO.ContactLink(this);
- this.s2Link = new OIMO.ContactLink(this);
- // The contact manifold of the contact.
- this.manifold = new OIMO.ContactManifold();
- this.buffer = [];// vector 4
- this.buffer.length = 4;
- this.buffer[0] = new OIMO.ImpulseDataBuffer();
- this.buffer[1] = new OIMO.ImpulseDataBuffer();
- this.buffer[2] = new OIMO.ImpulseDataBuffer();
- this.buffer[3] = new OIMO.ImpulseDataBuffer();
- this.points = this.manifold.points;
- this.constraint = new OIMO.ContactConstraint(this.manifold);
- }
- OIMO.Contact.prototype = {
- constructor: OIMO.Contact,
- mixRestitution: function (restitution1, restitution2) {
- return OIMO.sqrt(restitution1 * restitution2);
- },
- mixFriction: function (friction1, friction2) {
- return OIMO.sqrt(friction1 * friction2);
- },
- /**
- * Update the contact manifold.
- */
- updateManifold: function () {
- this.constraint.restitution = this.mixRestitution(this.shape1.restitution, this.shape2.restitution);
- this.constraint.friction = this.mixFriction(this.shape1.friction, this.shape2.friction);
- var numBuffers = this.manifold.numPoints;
- var i = numBuffers;
- while (i--) {
- //for(var i=0;i<numBuffers;i++){
- var b = this.buffer[i];
- var p = this.points[i];
- b.lp1X = p.localPoint1.x;
- b.lp1Y = p.localPoint1.y;
- b.lp1Z = p.localPoint1.z;
- b.lp2X = p.localPoint2.x;
- b.lp2Y = p.localPoint2.y;
- b.lp2Z = p.localPoint2.z;
- b.impulse = p.normalImpulse;
- }
- this.manifold.numPoints = 0;
- this.detector.detectCollision(this.shape1, this.shape2, this.manifold);
- var num = this.manifold.numPoints;
- if (num == 0) {
- this.touching = false;
- return;
- }
- this.touching = true;
- i = num;
- while (i--) {
- //for(i=0; i<num; i++){
- p = this.points[i];
- var lp1x = p.localPoint1.x;
- var lp1y = p.localPoint1.y;
- var lp1z = p.localPoint1.z;
- var lp2x = p.localPoint2.x;
- var lp2y = p.localPoint2.y;
- var lp2z = p.localPoint2.z;
- var index = -1;
- var minDistance = 0.0004;
- var j = numBuffers;
- while (j--) {
- //for(var j=0;j<numBuffers;j++){
- b = this.buffer[j];
- var dx = b.lp1X - lp1x;
- var dy = b.lp1Y - lp1y;
- var dz = b.lp1Z - lp1z;
- var distance1 = dx * dx + dy * dy + dz * dz;
- dx = b.lp2X - lp2x;
- dy = b.lp2Y - lp2y;
- dz = b.lp2Z - lp2z;
- var distance2 = dx * dx + dy * dy + dz * dz;
- if (distance1 < distance2) {
- if (distance1 < minDistance) {
- minDistance = distance1;
- index = j;
- }
- } else {
- if (distance2 < minDistance) {
- minDistance = distance2;
- index = j;
- }
- }
- }
- if (index != -1) {
- var tmp = this.buffer[index];
- this.buffer[index] = this.buffer[--numBuffers];
- this.buffer[numBuffers] = tmp;
- p.normalImpulse = tmp.impulse;
- p.warmStarted = true;
- } else {
- p.normalImpulse = 0;
- p.warmStarted = false;
- }
- }
- },
- /**
- * Attach the contact to the shapes.
- * @param shape1
- * @param shape2
- */
- attach: function (shape1, shape2) {
- this.shape1 = shape1;
- this.shape2 = shape2;
- this.body1 = shape1.parent;
- this.body2 = shape2.parent;
- this.manifold.body1 = this.body1;
- this.manifold.body2 = this.body2;
- this.constraint.body1 = this.body1;
- this.constraint.body2 = this.body2;
- this.constraint.attach();
- this.s1Link.shape = shape2;
- this.s1Link.body = this.body2;
- this.s2Link.shape = shape1;
- this.s2Link.body = this.body1;
- if (shape1.contactLink != null) (this.s1Link.next = shape1.contactLink).prev = this.s1Link;
- else this.s1Link.next = null;
- shape1.contactLink = this.s1Link;
- shape1.numContacts++;
- if (shape2.contactLink != null) (this.s2Link.next = shape2.contactLink).prev = this.s2Link;
- else this.s2Link.next = null;
- shape2.contactLink = this.s2Link;
- shape2.numContacts++;
- this.b1Link.shape = shape2;
- this.b1Link.body = this.body2;
- this.b2Link.shape = shape1;
- this.b2Link.body = this.body1;
- if (this.body1.contactLink != null) (this.b1Link.next = this.body1.contactLink).prev = this.b1Link;
- else this.b1Link.next = null;
- this.body1.contactLink = this.b1Link;
- this.body1.numContacts++;
- if (this.body2.contactLink != null) (this.b2Link.next = this.body2.contactLink).prev = this.b2Link;
- else this.b2Link.next = null;
- this.body2.contactLink = this.b2Link;
- this.body2.numContacts++;
- this.prev = null;
- this.next = null;
- this.persisting = true;
- this.sleeping = this.body1.sleeping && this.body2.sleeping;
- this.manifold.numPoints = 0;
- },
- /**
- * Detach the contact from the shapes.
- */
- detach: function () {
- var prev = this.s1Link.prev;
- var next = this.s1Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.shape1.contactLink == this.s1Link) this.shape1.contactLink = next;
- this.s1Link.prev = null;
- this.s1Link.next = null;
- this.s1Link.shape = null;
- this.s1Link.body = null;
- this.shape1.numContacts--;
- prev = this.s2Link.prev;
- next = this.s2Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.shape2.contactLink == this.s2Link) this.shape2.contactLink = next;
- this.s2Link.prev = null;
- this.s2Link.next = null;
- this.s2Link.shape = null;
- this.s2Link.body = null;
- this.shape2.numContacts--;
- prev = this.b1Link.prev;
- next = this.b1Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.body1.contactLink == this.b1Link) this.body1.contactLink = next;
- this.b1Link.prev = null;
- this.b1Link.next = null;
- this.b1Link.shape = null;
- this.b1Link.body = null;
- this.body1.numContacts--;
- prev = this.b2Link.prev;
- next = this.b2Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.body2.contactLink == this.b2Link) this.body2.contactLink = next;
- this.b2Link.prev = null;
- this.b2Link.next = null;
- this.b2Link.shape = null;
- this.b2Link.body = null;
- this.body2.numContacts--;
- this.manifold.body1 = null;
- this.manifold.body2 = null;
- this.constraint.body1 = null;
- this.constraint.body2 = null;
- this.constraint.detach();
- this.shape1 = null;
- this.shape2 = null;
- this.body1 = null;
- this.body2 = null;
- }
- }
- /**
- * ...
- * @author saharan
- */
- OIMO.ContactConstraint = function (manifold) {
- OIMO.Constraint.call(this);
- // The contact manifold of the constraint.
- this.manifold = manifold;
- // The coefficient of restitution of the constraint.
- this.restitution = NaN;
- // The coefficient of friction of the constraint.
- this.friction = NaN;
- this.p1 = null;
- this.p2 = null;
- this.lv1 = null;
- this.lv2 = null;
- this.av1 = null;
- this.av2 = null;
- this.i1 = null;
- this.i2 = null;
- this.ii1 = null;
- this.ii2 = null;
- this.m1 = NaN;
- this.m2 = NaN;
- this.num = 0;
- this.ps = manifold.points;
- this.cs = new OIMO.ContactPointDataBuffer();
- this.cs.next = new OIMO.ContactPointDataBuffer();
- this.cs.next.next = new OIMO.ContactPointDataBuffer();
- this.cs.next.next.next = new OIMO.ContactPointDataBuffer();
- }
- OIMO.ContactConstraint.prototype = Object.create(OIMO.Constraint.prototype);
- /**
- * Attach the constraint to the bodies.
- */
- OIMO.ContactConstraint.prototype.attach = function () {
- this.p1 = this.body1.position;
- this.p2 = this.body2.position;
- this.lv1 = this.body1.linearVelocity;
- this.av1 = this.body1.angularVelocity;
- this.lv2 = this.body2.linearVelocity;
- this.av2 = this.body2.angularVelocity;
- this.i1 = this.body1.inverseInertia;
- this.i2 = this.body2.inverseInertia;
- }
- /**
- * Detach the constraint from the bodies.
- */
- OIMO.ContactConstraint.prototype.detach = function () {
- this.p1 = null;
- this.p2 = null;
- this.lv1 = null;
- this.lv2 = null;
- this.av1 = null;
- this.av2 = null;
- this.i1 = null;
- this.i2 = null;
- }
- OIMO.ContactConstraint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.m1 = this.body1.inverseMass;
- this.m2 = this.body2.inverseMass;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- var ii1 = this.ii1.elements;
- var ii2 = this.ii2.elements;
- var p1x = this.p1.x;
- var p1y = this.p1.y;
- var p1z = this.p1.z;
- var p2x = this.p2.x;
- var p2y = this.p2.y;
- var p2z = this.p2.z;
- var m1m2 = this.m1 + this.m2;
- this.num = this.manifold.numPoints;
- var c = this.cs;
- for (var i = 0; i < this.num; i++) {
- var p = this.ps[i];
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- var tmp2X;
- var tmp2Y;
- var tmp2Z;
- tmp1X = p.position.x;
- tmp1Y = p.position.y;
- tmp1Z = p.position.z;
- var rp1X = tmp1X - p1x;
- var rp1Y = tmp1Y - p1y;
- var rp1Z = tmp1Z - p1z;
- var rp2X = tmp1X - p2x;
- var rp2Y = tmp1Y - p2y;
- var rp2Z = tmp1Z - p2z;
- c.rp1X = rp1X;
- c.rp1Y = rp1Y;
- c.rp1Z = rp1Z;
- c.rp2X = rp2X;
- c.rp2Y = rp2Y;
- c.rp2Z = rp2Z;
- c.norImp = p.normalImpulse;
- c.tanImp = p.tangentImpulse;
- c.binImp = p.binormalImpulse;
- var norX = p.normal.x;
- var norY = p.normal.y;
- var norZ = p.normal.z;
- var rvX = (this.lv2.x + this.av2.y * rp2Z - this.av2.z * rp2Y) - (this.lv1.x + this.av1.y * rp1Z - this.av1.z * rp1Y);
- var rvY = (this.lv2.y + this.av2.z * rp2X - this.av2.x * rp2Z) - (this.lv1.y + this.av1.z * rp1X - this.av1.x * rp1Z);
- var rvZ = (this.lv2.z + this.av2.x * rp2Y - this.av2.y * rp2X) - (this.lv1.z + this.av1.x * rp1Y - this.av1.y * rp1X);
- var rvn = norX * rvX + norY * rvY + norZ * rvZ;
- var tanX = rvX - rvn * norX;
- var tanY = rvY - rvn * norY;
- var tanZ = rvZ - rvn * norZ;
- var len = tanX * tanX + tanY * tanY + tanZ * tanZ;
- if (len > 0.04) {
- len = 1 / OIMO.sqrt(len);
- } else {
- tanX = norY * norX - norZ * norZ;
- tanY = -norZ * norY - norX * norX;
- tanZ = norX * norZ + norY * norY;
- len = 1 / OIMO.sqrt(tanX * tanX + tanY * tanY + tanZ * tanZ);
- }
- tanX *= len;
- tanY *= len;
- tanZ *= len;
- var binX = norY * tanZ - norZ * tanY;
- var binY = norZ * tanX - norX * tanZ;
- var binZ = norX * tanY - norY * tanX;
- c.norX = norX;
- c.norY = norY;
- c.norZ = norZ;
- c.tanX = tanX;
- c.tanY = tanY;
- c.tanZ = tanZ;
- c.binX = binX;
- c.binY = binY;
- c.binZ = binZ;
- c.norU1X = norX * this.m1;
- c.norU1Y = norY * this.m1;
- c.norU1Z = norZ * this.m1;
- c.norU2X = norX * this.m2;
- c.norU2Y = norY * this.m2;
- c.norU2Z = norZ * this.m2;
- c.tanU1X = tanX * this.m1;
- c.tanU1Y = tanY * this.m1;
- c.tanU1Z = tanZ * this.m1;
- c.tanU2X = tanX * this.m2;
- c.tanU2Y = tanY * this.m2;
- c.tanU2Z = tanZ * this.m2;
- c.binU1X = binX * this.m1;
- c.binU1Y = binY * this.m1;
- c.binU1Z = binZ * this.m1;
- c.binU2X = binX * this.m2;
- c.binU2Y = binY * this.m2;
- c.binU2Z = binZ * this.m2;
- var norT1X = rp1Y * norZ - rp1Z * norY;
- var norT1Y = rp1Z * norX - rp1X * norZ;
- var norT1Z = rp1X * norY - rp1Y * norX;
- var norT2X = rp2Y * norZ - rp2Z * norY;
- var norT2Y = rp2Z * norX - rp2X * norZ;
- var norT2Z = rp2X * norY - rp2Y * norX;
- var tanT1X = rp1Y * tanZ - rp1Z * tanY;
- var tanT1Y = rp1Z * tanX - rp1X * tanZ;
- var tanT1Z = rp1X * tanY - rp1Y * tanX;
- var tanT2X = rp2Y * tanZ - rp2Z * tanY;
- var tanT2Y = rp2Z * tanX - rp2X * tanZ;
- var tanT2Z = rp2X * tanY - rp2Y * tanX;
- var binT1X = rp1Y * binZ - rp1Z * binY;
- var binT1Y = rp1Z * binX - rp1X * binZ;
- var binT1Z = rp1X * binY - rp1Y * binX;
- var binT2X = rp2Y * binZ - rp2Z * binY;
- var binT2Y = rp2Z * binX - rp2X * binZ;
- var binT2Z = rp2X * binY - rp2Y * binX;
- var norTU1X = norT1X * ii1[0] + norT1Y * ii1[1] + norT1Z * ii1[2];
- var norTU1Y = norT1X * ii1[3] + norT1Y * ii1[4] + norT1Z * ii1[5];
- var norTU1Z = norT1X * ii1[6] + norT1Y * ii1[7] + norT1Z * ii1[8];
- var norTU2X = norT2X * ii2[0] + norT2Y * ii2[1] + norT2Z * ii2[2];
- var norTU2Y = norT2X * ii2[3] + norT2Y * ii2[4] + norT2Z * ii2[5];
- var norTU2Z = norT2X * ii2[6] + norT2Y * ii2[7] + norT2Z * ii2[8];
- var tanTU1X = tanT1X * ii1[0] + tanT1Y * ii1[1] + tanT1Z * ii1[2];
- var tanTU1Y = tanT1X * ii1[3] + tanT1Y * ii1[4] + tanT1Z * ii1[5];
- var tanTU1Z = tanT1X * ii1[6] + tanT1Y * ii1[7] + tanT1Z * ii1[8];
- var tanTU2X = tanT2X * ii2[0] + tanT2Y * ii2[1] + tanT2Z * ii2[2];
- var tanTU2Y = tanT2X * ii2[3] + tanT2Y * ii2[4] + tanT2Z * ii2[5];
- var tanTU2Z = tanT2X * ii2[6] + tanT2Y * ii2[7] + tanT2Z * ii2[8];
- var binTU1X = binT1X * ii1[0] + binT1Y * ii1[1] + binT1Z * ii1[2];
- var binTU1Y = binT1X * ii1[3] + binT1Y * ii1[4] + binT1Z * ii1[5];
- var binTU1Z = binT1X * ii1[6] + binT1Y * ii1[7] + binT1Z * ii1[8];
- var binTU2X = binT2X * ii2[0] + binT2Y * ii2[1] + binT2Z * ii2[2];
- var binTU2Y = binT2X * ii2[3] + binT2Y * ii2[4] + binT2Z * ii2[5];
- var binTU2Z = binT2X * ii2[6] + binT2Y * ii2[7] + binT2Z * ii2[8];
- c.norT1X = norT1X;
- c.norT1Y = norT1Y;
- c.norT1Z = norT1Z;
- c.tanT1X = tanT1X;
- c.tanT1Y = tanT1Y;
- c.tanT1Z = tanT1Z;
- c.binT1X = binT1X;
- c.binT1Y = binT1Y;
- c.binT1Z = binT1Z;
- c.norT2X = norT2X;
- c.norT2Y = norT2Y;
- c.norT2Z = norT2Z;
- c.tanT2X = tanT2X;
- c.tanT2Y = tanT2Y;
- c.tanT2Z = tanT2Z;
- c.binT2X = binT2X;
- c.binT2Y = binT2Y;
- c.binT2Z = binT2Z;
- c.norTU1X = norTU1X;
- c.norTU1Y = norTU1Y;
- c.norTU1Z = norTU1Z;
- c.tanTU1X = tanTU1X;
- c.tanTU1Y = tanTU1Y;
- c.tanTU1Z = tanTU1Z;
- c.binTU1X = binTU1X;
- c.binTU1Y = binTU1Y;
- c.binTU1Z = binTU1Z;
- c.norTU2X = norTU2X;
- c.norTU2Y = norTU2Y;
- c.norTU2Z = norTU2Z;
- c.tanTU2X = tanTU2X;
- c.tanTU2Y = tanTU2Y;
- c.tanTU2Z = tanTU2Z;
- c.binTU2X = binTU2X;
- c.binTU2Y = binTU2Y;
- c.binTU2Z = binTU2Z;
- tmp1X = norT1X * ii1[0] + norT1Y * ii1[1] + norT1Z * ii1[2];
- tmp1Y = norT1X * ii1[3] + norT1Y * ii1[4] + norT1Z * ii1[5];
- tmp1Z = norT1X * ii1[6] + norT1Y * ii1[7] + norT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = norT2X * ii2[0] + norT2Y * ii2[1] + norT2Z * ii2[2];
- tmp1Y = norT2X * ii2[3] + norT2Y * ii2[4] + norT2Z * ii2[5];
- tmp1Z = norT2X * ii2[6] + norT2Y * ii2[7] + norT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var norDen = 1 / (m1m2 + norX * tmp2X + norY * tmp2Y + norZ * tmp2Z);
- tmp1X = tanT1X * ii1[0] + tanT1Y * ii1[1] + tanT1Z * ii1[2];
- tmp1Y = tanT1X * ii1[3] + tanT1Y * ii1[4] + tanT1Z * ii1[5];
- tmp1Z = tanT1X * ii1[6] + tanT1Y * ii1[7] + tanT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = tanT2X * ii2[0] + tanT2Y * ii2[1] + tanT2Z * ii2[2];
- tmp1Y = tanT2X * ii2[3] + tanT2Y * ii2[4] + tanT2Z * ii2[5];
- tmp1Z = tanT2X * ii2[6] + tanT2Y * ii2[7] + tanT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var tanDen = 1 / (m1m2 + tanX * tmp2X + tanY * tmp2Y + tanZ * tmp2Z);
- tmp1X = binT1X * ii1[0] + binT1Y * ii1[1] + binT1Z * ii1[2];
- tmp1Y = binT1X * ii1[3] + binT1Y * ii1[4] + binT1Z * ii1[5];
- tmp1Z = binT1X * ii1[6] + binT1Y * ii1[7] + binT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = binT2X * ii2[0] + binT2Y * ii2[1] + binT2Z * ii2[2];
- tmp1Y = binT2X * ii2[3] + binT2Y * ii2[4] + binT2Z * ii2[5];
- tmp1Z = binT2X * ii2[6] + binT2Y * ii2[7] + binT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var binDen = 1 / (m1m2 + binX * tmp2X + binY * tmp2Y + binZ * tmp2Z);
- c.norDen = norDen;
- c.tanDen = tanDen;
- c.binDen = binDen;
- if (p.warmStarted) {
- var norImp = p.normalImpulse;
- this.lv1.x += c.norU1X * norImp;
- this.lv1.y += c.norU1Y * norImp;
- this.lv1.z += c.norU1Z * norImp;
- this.av1.x += norTU1X * norImp;
- this.av1.y += norTU1Y * norImp;
- this.av1.z += norTU1Z * norImp;
- this.lv2.x -= c.norU2X * norImp;
- this.lv2.y -= c.norU2Y * norImp;
- this.lv2.z -= c.norU2Z * norImp;
- this.av2.x -= norTU2X * norImp;
- this.av2.y -= norTU2Y * norImp;
- this.av2.z -= norTU2Z * norImp;
- c.norImp = norImp;
- c.tanImp = 0;
- c.binImp = 0;
- rvn = 0; // disable bouncing
- } else {
- c.norImp = 0;
- c.tanImp = 0;
- c.binImp = 0;
- }
- if (rvn > -1) {
- rvn = 0; // disable bouncing
- }
- var norTar = this.restitution * -rvn;
- var sepV = -(p.penetration + 0.005) * invTimeStep * 0.05; // allow 0.5cm error
- if (norTar < sepV) norTar = sepV;
- c.norTar = norTar;
- c.last = i == this.num - 1;
- c = c.next;
- }
- }
- OIMO.ContactConstraint.prototype.solve = function () {
- var lv1x = this.lv1.x;
- var lv1y = this.lv1.y;
- var lv1z = this.lv1.z;
- var lv2x = this.lv2.x;
- var lv2y = this.lv2.y;
- var lv2z = this.lv2.z;
- var av1x = this.av1.x;
- var av1y = this.av1.y;
- var av1z = this.av1.z;
- var av2x = this.av2.x;
- var av2y = this.av2.y;
- var av2z = this.av2.z;
- var c = this.cs;
- while (true) {
- var oldImp1;
- var newImp1;
- var oldImp2;
- var newImp2;
- var rvn;
- var norImp = c.norImp;
- var tanImp = c.tanImp;
- var binImp = c.binImp;
- var max = -norImp * this.friction;
- var rvX = lv2x - lv1x;
- var rvY = lv2y - lv1y;
- var rvZ = lv2z - lv1z;
- rvn =
- rvX * c.tanX + rvY * c.tanY + rvZ * c.tanZ +
- av2x * c.tanT2X + av2y * c.tanT2Y + av2z * c.tanT2Z -
- av1x * c.tanT1X - av1y * c.tanT1Y - av1z * c.tanT1Z
- ;
- oldImp1 = tanImp;
- newImp1 = rvn * c.tanDen;
- tanImp += newImp1;
- rvn =
- rvX * c.binX + rvY * c.binY + rvZ * c.binZ +
- av2x * c.binT2X + av2y * c.binT2Y + av2z * c.binT2Z -
- av1x * c.binT1X - av1y * c.binT1Y - av1z * c.binT1Z
- ;
- oldImp2 = binImp;
- newImp2 = rvn * c.binDen;
- binImp += newImp2;
- // cone friction clamp
- var len = tanImp * tanImp + binImp * binImp;
- if (len > max * max) {
- len = max / OIMO.sqrt(len);
- tanImp *= len;
- binImp *= len;
- }
- newImp1 = tanImp - oldImp1;
- newImp2 = binImp - oldImp2;
- lv1x += c.tanU1X * newImp1 + c.binU1X * newImp2;
- lv1y += c.tanU1Y * newImp1 + c.binU1Y * newImp2;
- lv1z += c.tanU1Z * newImp1 + c.binU1Z * newImp2;
- av1x += c.tanTU1X * newImp1 + c.binTU1X * newImp2;
- av1y += c.tanTU1Y * newImp1 + c.binTU1Y * newImp2;
- av1z += c.tanTU1Z * newImp1 + c.binTU1Z * newImp2;
- lv2x -= c.tanU2X * newImp1 + c.binU2X * newImp2;
- lv2y -= c.tanU2Y * newImp1 + c.binU2Y * newImp2;
- lv2z -= c.tanU2Z * newImp1 + c.binU2Z * newImp2;
- av2x -= c.tanTU2X * newImp1 + c.binTU2X * newImp2;
- av2y -= c.tanTU2Y * newImp1 + c.binTU2Y * newImp2;
- av2z -= c.tanTU2Z * newImp1 + c.binTU2Z * newImp2;
- // restitution part
- rvn =
- (lv2x - lv1x) * c.norX + (lv2y - lv1y) * c.norY + (lv2z - lv1z) * c.norZ +
- av2x * c.norT2X + av2y * c.norT2Y + av2z * c.norT2Z -
- av1x * c.norT1X - av1y * c.norT1Y - av1z * c.norT1Z;
- oldImp1 = norImp;
- newImp1 = (rvn - c.norTar) * c.norDen;
- norImp += newImp1;
- if (norImp > 0) norImp = 0;
- newImp1 = norImp - oldImp1;
- lv1x += c.norU1X * newImp1;
- lv1y += c.norU1Y * newImp1;
- lv1z += c.norU1Z * newImp1;
- av1x += c.norTU1X * newImp1;
- av1y += c.norTU1Y * newImp1;
- av1z += c.norTU1Z * newImp1;
- lv2x -= c.norU2X * newImp1;
- lv2y -= c.norU2Y * newImp1;
- lv2z -= c.norU2Z * newImp1;
- av2x -= c.norTU2X * newImp1;
- av2y -= c.norTU2Y * newImp1;
- av2z -= c.norTU2Z * newImp1;
- c.norImp = norImp;
- c.tanImp = tanImp;
- c.binImp = binImp;
- if (c.last) break;
- c = c.next;
- }
- this.lv1.x = lv1x;
- this.lv1.y = lv1y;
- this.lv1.z = lv1z;
- this.lv2.x = lv2x;
- this.lv2.y = lv2y;
- this.lv2.z = lv2z;
- this.av1.x = av1x;
- this.av1.y = av1y;
- this.av1.z = av1z;
- this.av2.x = av2x;
- this.av2.y = av2y;
- this.av2.z = av2z;
- }
- OIMO.ContactConstraint.prototype.postSolve = function () {
- var c = this.cs;
- var i = this.num;
- while (i--) {
- //for(var i=0;i<this.num;i++){
- var p = this.ps[i];
- p.normal.x = c.norX;
- p.normal.y = c.norY;
- p.normal.z = c.norZ;
- p.tangent.x = c.tanX;
- p.tangent.y = c.tanY;
- p.tangent.z = c.tanZ;
- p.binormal.x = c.binX;
- p.binormal.y = c.binY;
- p.binormal.z = c.binZ;
- p.normalImpulse = c.norImp;
- p.tangentImpulse = c.tanImp;
- p.binormalImpulse = c.binImp;
- p.normalDenominator = c.norDen;
- p.tangentDenominator = c.tanDen;
- p.binormalDenominator = c.binDen;
- c = c.next;
- }
- }
- /**
- * A link list of contacts.
- * @author saharan
- */
- OIMO.ContactLink = function (contact) {
- // The previous contact link.
- this.prev = null;
- // The next contact link.
- this.next = null;
- // The shape of the contact.
- this.shape = null;
- // The other rigid body.
- this.body = null;
- // The contact of the link.
- this.contact = contact;
- }
- /**
- * A contact manifold between two shapes.
- * @author saharan
- */
- OIMO.ContactManifold = function () {
- // The first rigid body.
- this.body1 = null;
- // The second rigid body.
- this.body2 = null;
- // The number of manifold points.
- this.numPoints = 0;
- // The manifold points.
- this.points = [];
- this.points.length = 4;
- this.points[0] = new OIMO.ManifoldPoint();
- this.points[1] = new OIMO.ManifoldPoint();
- this.points[2] = new OIMO.ManifoldPoint();
- this.points[3] = new OIMO.ManifoldPoint();
- }
- OIMO.ContactManifold.prototype = {
- constructor: OIMO.ContactManifold,
- /**
- * Reset the manifold.
- * @param shape1
- * @param shape2
- */
- reset: function (shape1, shape2) {
- this.body1 = shape1.parent;
- this.body2 = shape2.parent;
- this.numPoints = 0;
- },
- /**
- * Add a point into this manifold.
- * @param x
- * @param y
- * @param z
- * @param normalX
- * @param normalY
- * @param normalZ
- * @param penetration
- * @param flip
- */
- addPoint: function (x, y, z, normalX, normalY, normalZ, penetration, flip) {
- var p = this.points[this.numPoints++];
- p.position.x = x;
- p.position.y = y;
- p.position.z = z;
- var r = this.body1.rotation;
- var rx = x - this.body1.position.x;
- var ry = y - this.body1.position.y;
- var rz = z - this.body1.position.z;
- var tr = r.elements;
- p.localPoint1.x = rx * tr[0] + ry * tr[3] + rz * tr[6];
- p.localPoint1.y = rx * tr[1] + ry * tr[4] + rz * tr[7];
- p.localPoint1.z = rx * tr[2] + ry * tr[5] + rz * tr[8];
- r = this.body2.rotation;
- rx = x - this.body2.position.x;
- ry = y - this.body2.position.y;
- rz = z - this.body2.position.z;
- p.localPoint2.x = rx * tr[0] + ry * tr[3] + rz * tr[6];
- p.localPoint2.y = rx * tr[1] + ry * tr[4] + rz * tr[7];
- p.localPoint2.z = rx * tr[2] + ry * tr[5] + rz * tr[8];
- p.normalImpulse = 0;
- if (flip) {
- p.normal.x = -normalX;
- p.normal.y = -normalY;
- p.normal.z = -normalZ;
- } else {
- p.normal.x = normalX;
- p.normal.y = normalY;
- p.normal.z = normalZ;
- }
- p.penetration = penetration;
- p.warmStarted = false;
- }
- }
- OIMO.ContactPointDataBuffer = function () {
- this.norX = NaN;
- this.norY = NaN;
- this.norZ = NaN;
- this.tanX = NaN;
- this.tanY = NaN;
- this.tanZ = NaN;
- this.binX = NaN;
- this.binY = NaN;
- this.binZ = NaN;
- this.rp1X = NaN;
- this.rp1Y = NaN;
- this.rp1Z = NaN;
- this.rp2X = NaN;
- this.rp2Y = NaN;
- this.rp2Z = NaN;
- this.norU1X = NaN;
- this.norU1Y = NaN;
- this.norU1Z = NaN;
- this.norU2X = NaN;
- this.norU2Y = NaN;
- this.norU2Z = NaN;
- this.tanU1X = NaN;
- this.tanU1Y = NaN;
- this.tanU1Z = NaN;
- this.tanU2X = NaN;
- this.tanU2Y = NaN;
- this.tanU2Z = NaN;
- this.binU1X = NaN;
- this.binU1Y = NaN;
- this.binU1Z = NaN;
- this.binU2X = NaN;
- this.binU2Y = NaN;
- this.binU2Z = NaN;
- this.norT1X = NaN;
- this.norT1Y = NaN;
- this.norT1Z = NaN;
- this.norT2X = NaN;
- this.norT2Y = NaN;
- this.norT2Z = NaN;
- this.tanT1X = NaN;
- this.tanT1Y = NaN;
- this.tanT1Z = NaN;
- this.tanT2X = NaN;
- this.tanT2Y = NaN;
- this.tanT2Z = NaN;
- this.binT1X = NaN;
- this.binT1Y = NaN;
- this.binT1Z = NaN;
- this.binT2X = NaN;
- this.binT2Y = NaN;
- this.binT2Z = NaN;
- this.norTU1X = NaN;
- this.norTU1Y = NaN;
- this.norTU1Z = NaN;
- this.norTU2X = NaN;
- this.norTU2Y = NaN;
- this.norTU2Z = NaN;
- this.tanTU1X = NaN;
- this.tanTU1Y = NaN;
- this.tanTU1Z = NaN;
- this.tanTU2X = NaN;
- this.tanTU2Y = NaN;
- this.tanTU2Z = NaN;
- this.binTU1X = NaN;
- this.binTU1Y = NaN;
- this.binTU1Z = NaN;
- this.binTU2X = NaN;
- this.binTU2Y = NaN;
- this.binTU2Z = NaN;
- this.norImp = NaN;
- this.tanImp = NaN;
- this.binImp = NaN;
- this.norDen = NaN;
- this.tanDen = NaN;
- this.binDen = NaN;
- this.norTar = NaN;
- this.next = null;
- this.last = false;
- }
- OIMO.ImpulseDataBuffer = function () {
- this.lp1X = NaN;
- this.lp1Y = NaN;
- this.lp1Z = NaN;
- this.lp2X = NaN;
- this.lp2Y = NaN;
- this.lp2Z = NaN;
- this.impulse = NaN;
- }
- /**
- * The class holds details of the contact point.
- * @author saharan
- */
- OIMO.ManifoldPoint = function () {
- // Whether this manifold point is persisting or not.
- this.warmStarted = false;
- // The position of this manifold point.
- this.position = new OIMO.Vec3();
- // The position in the first shape's coordinate.
- this.localPoint1 = new OIMO.Vec3();
- // The position in the second shape's coordinate.
- this.localPoint2 = new OIMO.Vec3();
- // The normal vector of this manifold point.
- this.normal = new OIMO.Vec3();
- // The tangent vector of this manifold point.
- this.tangent = new OIMO.Vec3();
- // The binormal vector of this manifold point.
- this.binormal = new OIMO.Vec3();
- // The impulse in normal direction.
- this.normalImpulse = 0;
- // The impulse in tangent direction.
- this.tangentImpulse = 0;
- // The impulse in binormal direction.
- this.binormalImpulse = 0;
- // The denominator in normal direction.
- this.normalDenominator = 0;
- // The denominator in tangent direction.
- this.tangentDenominator = 0;
- // The denominator in binormal direction.
- this.binormalDenominator = 0;
- // The depth of penetration.
- this.penetration = 0;
- }
- /**
- * This class holds mass information of a shape.
- * @author saharan
- */
- OIMO.MassInfo = function () {
- // Mass of the shape.
- this.mass = 0;
- // The moment inertia of the shape.
- this.inertia = new OIMO.Mat33();
- };
- /**
- * A shape is used to detect collisions of rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.Shape = function (config) {
- this.type = OIMO.SHAPE_NULL;
- // The global identification of the shape should be unique to the shape.
- this.id = OIMO.nextID++;
- // The previous shape in parent rigid body.
- this.prev = null;
- // The next shape in parent rigid body.
- this.next = null;
- // The proxy of the shape used for broad-phase collision detection.
- this.proxy = null;
- // The parent rigid body of the shape.
- this.parent = null;
- // The linked list of the contacts with the shape.
- this.contactLink = null;
- // The number of the contacts with the shape.
- this.numContacts = 0;
- // The center of gravity of the shape in world coordinate system.
- this.position = new OIMO.Vec3();
- // The rotation matrix of the shape in world coordinate system
- this.rotation = new OIMO.Mat33();
- // The position of the shape in parent's coordinate system.
- this.relativePosition = new OIMO.Vec3().copy(config.relativePosition);
- // The rotation matrix of the shape in parent's coordinate system.
- this.relativeRotation = new OIMO.Mat33().copy(config.relativeRotation);
- // The axis-aligned bounding box of the shape.
- this.aabb = new OIMO.AABB();
- // The density of the shape.
- this.density = config.density;
- // The coefficient of friction of the shape.
- this.friction = config.friction;
- // The coefficient of restitution of the shape.
- this.restitution = config.restitution;
- // The bits of the collision groups to which the shape belongs.
- this.belongsTo = config.belongsTo;
- // The bits of the collision groups with which the shape collides.
- this.collidesWith = config.collidesWith;
- };
- OIMO.Shape.prototype = {
- constructor: OIMO.Shape,
- // Calculate the mass information of the shape.
- calculateMassInfo: function (out) {
- OIMO.Error("Shape", "Inheritance error.");
- },
- // Update the proxy of the shape.
- updateProxy: function () {
- OIMO.Error("Shape", "Inheritance error.");
- }
- };
- /**
- * A shape configuration holds common configuration data for constructing a shape.
- * Shape configurations can be reused safely.
- * @author saharan
- */
- OIMO.ShapeConfig = function () {
- // The position of the shape in parent's coordinate system.
- this.relativePosition = new OIMO.Vec3();
- // The rotation matrix of the shape in parent's coordinate system.
- this.relativeRotation = new OIMO.Mat33();
- // The coefficient of friction of the shape.
- this.friction = 0.4;
- // The coefficient of restitution of the shape.
- this.restitution = 0.2;
- // The density of the shape.
- this.density = 1;
- // The bits of the collision groups to which the shape belongs.
- this.belongsTo = 1;
- // The bits of the collision groups with which the shape collides.
- this.collidesWith = 0xffffffff;
- };
- /**
- * A box shape.
- * @author saharan
- * @author lo-th
- */
- OIMO.BoxShape = function (config, Width, Height, Depth) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_BOX;
- // The width of the box.
- this.width = Width;
- // The height of the box.
- this.height = Height;
- // The depth of the box.
- this.depth = Depth;
- // The half-width of the box.
- this.halfWidth = Width * 0.5;
- // The half-height of the box.
- this.halfHeight = Height * 0.5;
- // The half-depth of the box.
- this.halfDepth = Depth * 0.5;
- this.dimentions = new OIMO_ARRAY_TYPE(18);
- this.elements = new OIMO_ARRAY_TYPE(24);
- };
- OIMO.BoxShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.BoxShape.prototype.constructor = OIMO.BoxShape;
- OIMO.BoxShape.prototype.calculateMassInfo = function (out) {
- var mass = this.width * this.height * this.depth * this.density;
- var divid = 1 / 12;
- out.mass = mass;
- out.inertia.set(
- mass * (this.height * this.height + this.depth * this.depth) * divid, 0, 0,
- 0, mass * (this.width * this.width + this.depth * this.depth) * divid, 0,
- 0, 0, mass * (this.width * this.width + this.height * this.height) * divid
- );
- };
- OIMO.BoxShape.prototype.updateProxy = function () {
- var te = this.rotation.elements;
- var di = this.dimentions;
- // Width
- di[0] = te[0];
- di[1] = te[3];
- di[2] = te[6];
- // Height
- di[3] = te[1];
- di[4] = te[4];
- di[5] = te[7];
- // Depth
- di[6] = te[2];
- di[7] = te[5];
- di[8] = te[8];
- // halp Width
- di[9] = te[0] * this.halfWidth;
- di[10] = te[3] * this.halfWidth;
- di[11] = te[6] * this.halfWidth;
- // halp Height
- di[12] = te[1] * this.halfHeight;
- di[13] = te[4] * this.halfHeight;
- di[14] = te[7] * this.halfHeight;
- // halp Depth
- di[15] = te[2] * this.halfDepth;
- di[16] = te[5] * this.halfDepth;
- di[17] = te[8] * this.halfDepth;
- var wx = di[9];
- var wy = di[10];
- var wz = di[11];
- var hx = di[12];
- var hy = di[13];
- var hz = di[14];
- var dx = di[15];
- var dy = di[16];
- var dz = di[17];
- var x = this.position.x;
- var y = this.position.y;
- var z = this.position.z;
- var v = this.elements;
- //v1
- v[0] = x + wx + hx + dx;
- v[1] = y + wy + hy + dy;
- v[2] = z + wz + hz + dz;
- //v2
- v[3] = x + wx + hx - dx;
- v[4] = y + wy + hy - dy;
- v[5] = z + wz + hz - dz;
- //v3
- v[6] = x + wx - hx + dx;
- v[7] = y + wy - hy + dy;
- v[8] = z + wz - hz + dz;
- //v4
- v[9] = x + wx - hx - dx;
- v[10] = y + wy - hy - dy;
- v[11] = z + wz - hz - dz;
- //v5
- v[12] = x - wx + hx + dx;
- v[13] = y - wy + hy + dy;
- v[14] = z - wz + hz + dz;
- //v6
- v[15] = x - wx + hx - dx;
- v[16] = y - wy + hy - dy;
- v[17] = z - wz + hz - dz;
- //v7
- v[18] = x - wx - hx + dx;
- v[19] = y - wy - hy + dy;
- v[20] = z - wz - hz + dz;
- //v8
- v[21] = x - wx - hx - dx;
- v[22] = y - wy - hy - dy;
- v[23] = z - wz - hz - dz;
- var w = di[9] < 0 ? -di[9] : di[9];
- var h = di[10] < 0 ? -di[10] : di[10];
- var d = di[11] < 0 ? -di[11] : di[11];
- w = di[12] < 0 ? w - di[12] : w + di[12];
- h = di[13] < 0 ? h - di[13] : h + di[13];
- d = di[14] < 0 ? d - di[14] : d + di[14];
- w = di[15] < 0 ? w - di[15] : w + di[15];
- h = di[16] < 0 ? h - di[16] : h + di[16];
- d = di[17] < 0 ? d - di[17] : d + di[17];
- var p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - w - p, this.position.x + w + p,
- this.position.y - h - p, this.position.y + h + p,
- this.position.z - d - p, this.position.z + d + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A sphere shape.
- * @author saharan
- * @author lo-th
- */
- OIMO.SphereShape = function (config, radius) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_SPHERE;
- // The radius of the shape.
- this.radius = radius;
- };
- OIMO.SphereShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.SphereShape.prototype.constructor = OIMO.SphereShape;
- OIMO.SphereShape.prototype.calculateMassInfo = function (out) {
- var mass = 1.333 * OIMO.PI * this.radius * this.radius * this.radius * this.density;
- out.mass = mass;
- var inertia = mass * this.radius * this.radius * 0.4;
- out.inertia.set(inertia, 0, 0, 0, inertia, 0, 0, 0, inertia);
- };
- OIMO.SphereShape.prototype.updateProxy = function () {
- var p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - this.radius - p, this.position.x + this.radius + p,
- this.position.y - this.radius - p, this.position.y + this.radius + p,
- this.position.z - this.radius - p, this.position.z + this.radius + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A cylinder shap.
- * @author saharan
- * @author lo-th
- */
- OIMO.CylinderShape = function (config, radius, height) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_CYLINDER;
- this.radius = radius;
- this.height = height;
- this.halfHeight = height * 0.5;
- this.normalDirection = new OIMO.Vec3();
- this.halfDirection = new OIMO.Vec3();
- };
- OIMO.CylinderShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.CylinderShape.prototype.constructor = OIMO.CylinderShape;
- OIMO.CylinderShape.prototype.calculateMassInfo = function (out) {
- var rsq = this.radius * this.radius;
- var mass = OIMO.PI * rsq * this.height * this.density;
- var inertiaXZ = ((0.25 * rsq) + (0.0833 * this.height * this.height)) * mass;
- var inertiaY = 0.5 * rsq;
- out.mass = mass;
- out.inertia.set(inertiaXZ, 0, 0, 0, inertiaY, 0, 0, 0, inertiaXZ);
- };
- OIMO.CylinderShape.prototype.updateProxy = function () {
- var te = this.rotation.elements;
- var len, wx, hy, dz, xx, yy, zz, w, h, d, p;
- xx = te[1] * te[1];
- yy = te[4] * te[4];
- zz = te[7] * te[7];
- this.normalDirection.set(te[1], te[4], te[7]);
- this.halfDirection.scale(this.normalDirection, this.halfHeight);
- wx = 1 - xx;
- len = OIMO.sqrt(wx * wx + xx * yy + xx * zz);
- if (len > 0) len = this.radius / len;
- wx *= len;
- hy = 1 - yy;
- len = OIMO.sqrt(yy * xx + hy * hy + yy * zz);
- if (len > 0) len = this.radius / len;
- hy *= len;
- dz = 1 - zz;
- len = OIMO.sqrt(zz * xx + zz * yy + dz * dz);
- if (len > 0) len = this.radius / len;
- dz *= len;
- w = this.halfDirection.x < 0 ? -this.halfDirection.x : this.halfDirection.x;
- h = this.halfDirection.y < 0 ? -this.halfDirection.y : this.halfDirection.y;
- d = this.halfDirection.z < 0 ? -this.halfDirection.z : this.halfDirection.z;
- w = wx < 0 ? w - wx : w + wx;
- h = hy < 0 ? h - hy : h + hy;
- d = dz < 0 ? d - dz : d + dz;
- p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - w - p, this.position.x + w + p,
- this.position.y - h - p, this.position.y + h + p,
- this.position.z - d - p, this.position.z + d + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A tetra shape.
- * @author xprogram
- */
- OIMO.TetraShape = function (config, p1, p2, p3, p4) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_TETRA;
- // Vertices and faces of tetra
- this.verts = [p1, p2, p3, p4];
- this.faces = [
- mtri(0, 1, 2),
- mtri(1, 2, 3),
- mtri(2, 3, 4),
- mtri(4, 0, 1),
- ];
- };
- OIMO.TetraShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.TetraShape.prototype.constructor = OIMO.TetraShape;
- OIMO.TetraShape.prototype.calculateMassInfo = function () {
- // I guess you could calculate box mass and split it
- // in half for the tetra...
- };
- OIMO.TetraShape.prototype.updateProxy = function () {
- this.aabb.setFromPoints(this.verts);
- if (this.proxy !== null)
- this.proxy.update();
- };
- function mtri(a, b, c) {
- return { a: a, b: b, c: c };
- }
- OIMO.CollisionDetector = function () {
- this.flip = false;
- };
- OIMO.CollisionDetector.prototype = {
- constructor: OIMO.CollisionDetector,
- detectCollision: function (shape1, shape2, manifold) {
- OIMO.Error("CollisionDetector", "Inheritance error.");
- }
- };
- /**
- * A collision detector which detects collisions between two boxes.
- * @author saharan
- */
- OIMO.BoxBoxCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- this.clipVertices1 = new OIMO_ARRAY_TYPE(24); // 8 vertices x,y,z
- this.clipVertices2 = new OIMO_ARRAY_TYPE(24);
- this.used = new OIMO_ARRAY_TYPE(8);
- this.INF = 1 / 0;
- };
- OIMO.BoxBoxCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.BoxBoxCollisionDetector.prototype.constructor = OIMO.BoxBoxCollisionDetector;
- OIMO.BoxBoxCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- // What you are doing
- // · I to prepare a separate axis of the fifteen
- //-Six in each of three normal vectors of the xyz direction of the box both
- // · Remaining nine 3x3 a vector perpendicular to the side of the box 2 and the side of the box 1
- // · Calculate the depth to the separation axis
- // Calculates the distance using the inner product and put the amount of embedment
- // · However a vertical separation axis and side to weight a little to avoid vibration
- // And end when there is a separate axis that is remote even one
- // · I look for separation axis with little to dent most
- // Men and if separation axis of the first six - end collision
- // Heng If it separate axis of nine other - side collision
- // Heng - case of a side collision
- // · Find points of two sides on which you made the separation axis
- // Calculates the point of closest approach of a straight line consisting of separate axis points obtained, and the collision point
- //-Surface - the case of the plane crash
- //-Box A, box B and the other a box of better made a separate axis
- // • The surface A and the plane that made the separation axis of the box A, and B to the surface the face of the box B close in the opposite direction to the most isolated axis
- // When viewed from the front surface A, and the cut part exceeding the area of the surface A is a surface B
- //-Plane B becomes the 3-8 triangle, I a candidate for the collision point the vertex of surface B
- // • If more than one candidate 5 exists, scraping up to four
- // For potential collision points of all, to examine the distance between the surface A
- // • If you were on the inside surface of A, and the collision point
- var b1;
- var b2;
- if (shape1.id < shape2.id) {
- b1 = (shape1);
- b2 = (shape2);
- } else {
- b1 = (shape2);
- b2 = (shape1);
- }
- var V1 = b1.elements;
- var V2 = b2.elements;
- var D1 = b1.dimentions;
- var D2 = b2.dimentions;
- var p1 = b1.position;
- var p2 = b2.position;
- var p1x = p1.x;
- var p1y = p1.y;
- var p1z = p1.z;
- var p2x = p2.x;
- var p2y = p2.y;
- var p2z = p2.z;
- // diff
- var dx = p2x - p1x;
- var dy = p2y - p1y;
- var dz = p2z - p1z;
- // distance
- var w1 = b1.halfWidth;
- var h1 = b1.halfHeight;
- var d1 = b1.halfDepth;
- var w2 = b2.halfWidth;
- var h2 = b2.halfHeight;
- var d2 = b2.halfDepth;
- // direction
- // ----------------------------
- // 15 separating axes
- // 1~6: face
- // 7~f: edge
- // http://marupeke296.com/COL_3D_No13_OBBvsOBB.html
- // ----------------------------
- var a1x = D1[0];
- var a1y = D1[1];
- var a1z = D1[2];
- var a2x = D1[3];
- var a2y = D1[4];
- var a2z = D1[5];
- var a3x = D1[6];
- var a3y = D1[7];
- var a3z = D1[8];
- var d1x = D1[9];
- var d1y = D1[10];
- var d1z = D1[11];
- var d2x = D1[12];
- var d2y = D1[13];
- var d2z = D1[14];
- var d3x = D1[15];
- var d3y = D1[16];
- var d3z = D1[17];
- var a4x = D2[0];
- var a4y = D2[1];
- var a4z = D2[2];
- var a5x = D2[3];
- var a5y = D2[4];
- var a5z = D2[5];
- var a6x = D2[6];
- var a6y = D2[7];
- var a6z = D2[8];
- var d4x = D2[9];
- var d4y = D2[10];
- var d4z = D2[11];
- var d5x = D2[12];
- var d5y = D2[13];
- var d5z = D2[14];
- var d6x = D2[15];
- var d6y = D2[16];
- var d6z = D2[17];
- var a7x = a1y * a4z - a1z * a4y;
- var a7y = a1z * a4x - a1x * a4z;
- var a7z = a1x * a4y - a1y * a4x;
- var a8x = a1y * a5z - a1z * a5y;
- var a8y = a1z * a5x - a1x * a5z;
- var a8z = a1x * a5y - a1y * a5x;
- var a9x = a1y * a6z - a1z * a6y;
- var a9y = a1z * a6x - a1x * a6z;
- var a9z = a1x * a6y - a1y * a6x;
- var aax = a2y * a4z - a2z * a4y;
- var aay = a2z * a4x - a2x * a4z;
- var aaz = a2x * a4y - a2y * a4x;
- var abx = a2y * a5z - a2z * a5y;
- var aby = a2z * a5x - a2x * a5z;
- var abz = a2x * a5y - a2y * a5x;
- var acx = a2y * a6z - a2z * a6y;
- var acy = a2z * a6x - a2x * a6z;
- var acz = a2x * a6y - a2y * a6x;
- var adx = a3y * a4z - a3z * a4y;
- var ady = a3z * a4x - a3x * a4z;
- var adz = a3x * a4y - a3y * a4x;
- var aex = a3y * a5z - a3z * a5y;
- var aey = a3z * a5x - a3x * a5z;
- var aez = a3x * a5y - a3y * a5x;
- var afx = a3y * a6z - a3z * a6y;
- var afy = a3z * a6x - a3x * a6z;
- var afz = a3x * a6y - a3y * a6x;
- // right or left flags
- var right1;
- var right2;
- var right3;
- var right4;
- var right5;
- var right6;
- var right7;
- var right8;
- var right9;
- var righta;
- var rightb;
- var rightc;
- var rightd;
- var righte;
- var rightf;
- // overlapping distances
- var overlap1;
- var overlap2;
- var overlap3;
- var overlap4;
- var overlap5;
- var overlap6;
- var overlap7;
- var overlap8;
- var overlap9;
- var overlapa;
- var overlapb;
- var overlapc;
- var overlapd;
- var overlape;
- var overlapf;
- // invalid flags
- var invalid7 = false;
- var invalid8 = false;
- var invalid9 = false;
- var invalida = false;
- var invalidb = false;
- var invalidc = false;
- var invalidd = false;
- var invalide = false;
- var invalidf = false;
- // temporary variables
- var len;
- var len1;
- var len2;
- var dot1;
- var dot2;
- var dot3;
- // try axis 1
- len = a1x * dx + a1y * dy + a1z * dz;
- right1 = len > 0;
- if (!right1) len = -len;
- len1 = w1;
- dot1 = a1x * a4x + a1y * a4y + a1z * a4z;
- dot2 = a1x * a5x + a1y * a5y + a1z * a5z;
- dot3 = a1x * a6x + a1y * a6y + a1z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap1 = len - len1 - len2;
- if (overlap1 > 0) return;
- // try axis 2
- len = a2x * dx + a2y * dy + a2z * dz;
- right2 = len > 0;
- if (!right2) len = -len;
- len1 = h1;
- dot1 = a2x * a4x + a2y * a4y + a2z * a4z;
- dot2 = a2x * a5x + a2y * a5y + a2z * a5z;
- dot3 = a2x * a6x + a2y * a6y + a2z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap2 = len - len1 - len2;
- if (overlap2 > 0) return;
- // try axis 3
- len = a3x * dx + a3y * dy + a3z * dz;
- right3 = len > 0;
- if (!right3) len = -len;
- len1 = d1;
- dot1 = a3x * a4x + a3y * a4y + a3z * a4z;
- dot2 = a3x * a5x + a3y * a5y + a3z * a5z;
- dot3 = a3x * a6x + a3y * a6y + a3z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap3 = len - len1 - len2;
- if (overlap3 > 0) return;
- // try axis 4
- len = a4x * dx + a4y * dy + a4z * dz;
- right4 = len > 0;
- if (!right4) len = -len;
- dot1 = a4x * a1x + a4y * a1y + a4z * a1z;
- dot2 = a4x * a2x + a4y * a2y + a4z * a2z;
- dot3 = a4x * a3x + a4y * a3y + a4z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = w2;
- overlap4 = (len - len1 - len2) * 1.0;
- if (overlap4 > 0) return;
- // try axis 5
- len = a5x * dx + a5y * dy + a5z * dz;
- right5 = len > 0;
- if (!right5) len = -len;
- dot1 = a5x * a1x + a5y * a1y + a5z * a1z;
- dot2 = a5x * a2x + a5y * a2y + a5z * a2z;
- dot3 = a5x * a3x + a5y * a3y + a5z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = h2;
- overlap5 = (len - len1 - len2) * 1.0;
- if (overlap5 > 0) return;
- // try axis 6
- len = a6x * dx + a6y * dy + a6z * dz;
- right6 = len > 0;
- if (!right6) len = -len;
- dot1 = a6x * a1x + a6y * a1y + a6z * a1z;
- dot2 = a6x * a2x + a6y * a2y + a6z * a2z;
- dot3 = a6x * a3x + a6y * a3y + a6z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = d2;
- overlap6 = (len - len1 - len2) * 1.0;
- if (overlap6 > 0) return;
- // try axis 7
- len = a7x * a7x + a7y * a7y + a7z * a7z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a7x *= len;
- a7y *= len;
- a7z *= len;
- len = a7x * dx + a7y * dy + a7z * dz;
- right7 = len > 0;
- if (!right7) len = -len;
- dot1 = a7x * a2x + a7y * a2y + a7z * a2z;
- dot2 = a7x * a3x + a7y * a3y + a7z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a7x * a5x + a7y * a5y + a7z * a5z;
- dot2 = a7x * a6x + a7y * a6y + a7z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlap7 = len - len1 - len2;
- if (overlap7 > 0) return;
- } else {
- right7 = false;
- overlap7 = 0;
- invalid7 = true;
- }
- // try axis 8
- len = a8x * a8x + a8y * a8y + a8z * a8z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a8x *= len;
- a8y *= len;
- a8z *= len;
- len = a8x * dx + a8y * dy + a8z * dz;
- right8 = len > 0;
- if (!right8) len = -len;
- dot1 = a8x * a2x + a8y * a2y + a8z * a2z;
- dot2 = a8x * a3x + a8y * a3y + a8z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a8x * a4x + a8y * a4y + a8z * a4z;
- dot2 = a8x * a6x + a8y * a6y + a8z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlap8 = len - len1 - len2;
- if (overlap8 > 0) return;
- } else {
- right8 = false;
- overlap8 = 0;
- invalid8 = true;
- }
- // try axis 9
- len = a9x * a9x + a9y * a9y + a9z * a9z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a9x *= len;
- a9y *= len;
- a9z *= len;
- len = a9x * dx + a9y * dy + a9z * dz;
- right9 = len > 0;
- if (!right9) len = -len;
- dot1 = a9x * a2x + a9y * a2y + a9z * a2z;
- dot2 = a9x * a3x + a9y * a3y + a9z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a9x * a4x + a9y * a4y + a9z * a4z;
- dot2 = a9x * a5x + a9y * a5y + a9z * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlap9 = len - len1 - len2;
- if (overlap9 > 0) return;
- } else {
- right9 = false;
- overlap9 = 0;
- invalid9 = true;
- }
- // try axis 10
- len = aax * aax + aay * aay + aaz * aaz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- aax *= len;
- aay *= len;
- aaz *= len;
- len = aax * dx + aay * dy + aaz * dz;
- righta = len > 0;
- if (!righta) len = -len;
- dot1 = aax * a1x + aay * a1y + aaz * a1z;
- dot2 = aax * a3x + aay * a3y + aaz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = aax * a5x + aay * a5y + aaz * a5z;
- dot2 = aax * a6x + aay * a6y + aaz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlapa = len - len1 - len2;
- if (overlapa > 0) return;
- } else {
- righta = false;
- overlapa = 0;
- invalida = true;
- }
- // try axis 11
- len = abx * abx + aby * aby + abz * abz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- abx *= len;
- aby *= len;
- abz *= len;
- len = abx * dx + aby * dy + abz * dz;
- rightb = len > 0;
- if (!rightb) len = -len;
- dot1 = abx * a1x + aby * a1y + abz * a1z;
- dot2 = abx * a3x + aby * a3y + abz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = abx * a4x + aby * a4y + abz * a4z;
- dot2 = abx * a6x + aby * a6y + abz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlapb = len - len1 - len2;
- if (overlapb > 0) return;
- } else {
- rightb = false;
- overlapb = 0;
- invalidb = true;
- }
- // try axis 12
- len = acx * acx + acy * acy + acz * acz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- acx *= len;
- acy *= len;
- acz *= len;
- len = acx * dx + acy * dy + acz * dz;
- rightc = len > 0;
- if (!rightc) len = -len;
- dot1 = acx * a1x + acy * a1y + acz * a1z;
- dot2 = acx * a3x + acy * a3y + acz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = acx * a4x + acy * a4y + acz * a4z;
- dot2 = acx * a5x + acy * a5y + acz * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlapc = len - len1 - len2;
- if (overlapc > 0) return;
- } else {
- rightc = false;
- overlapc = 0;
- invalidc = true;
- }
- // try axis 13
- len = adx * adx + ady * ady + adz * adz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- adx *= len;
- ady *= len;
- adz *= len;
- len = adx * dx + ady * dy + adz * dz;
- rightd = len > 0;
- if (!rightd) len = -len;
- dot1 = adx * a1x + ady * a1y + adz * a1z;
- dot2 = adx * a2x + ady * a2y + adz * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = adx * a5x + ady * a5y + adz * a5z;
- dot2 = adx * a6x + ady * a6y + adz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlapd = len - len1 - len2;
- if (overlapd > 0) return;
- } else {
- rightd = false;
- overlapd = 0;
- invalidd = true;
- }
- // try axis 14
- len = aex * aex + aey * aey + aez * aez;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- aex *= len;
- aey *= len;
- aez *= len;
- len = aex * dx + aey * dy + aez * dz;
- righte = len > 0;
- if (!righte) len = -len;
- dot1 = aex * a1x + aey * a1y + aez * a1z;
- dot2 = aex * a2x + aey * a2y + aez * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = aex * a4x + aey * a4y + aez * a4z;
- dot2 = aex * a6x + aey * a6y + aez * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlape = len - len1 - len2;
- if (overlape > 0) return;
- } else {
- righte = false;
- overlape = 0;
- invalide = true;
- }
- // try axis 15
- len = afx * afx + afy * afy + afz * afz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- afx *= len;
- afy *= len;
- afz *= len;
- len = afx * dx + afy * dy + afz * dz;
- rightf = len > 0;
- if (!rightf) len = -len;
- dot1 = afx * a1x + afy * a1y + afz * a1z;
- dot2 = afx * a2x + afy * a2y + afz * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = afx * a4x + afy * a4y + afz * a4z;
- dot2 = afx * a5x + afy * a5y + afz * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlapf = len - len1 - len2;
- if (overlapf > 0) return;
- } else {
- rightf = false;
- overlapf = 0;
- invalidf = true;
- }
- // boxes are overlapping
- var depth = overlap1;
- var depth2 = overlap1;
- var minIndex = 0;
- var right = right1;
- if (overlap2 > depth2) {
- depth = overlap2;
- depth2 = overlap2;
- minIndex = 1;
- right = right2;
- }
- if (overlap3 > depth2) {
- depth = overlap3;
- depth2 = overlap3;
- minIndex = 2;
- right = right3;
- }
- if (overlap4 > depth2) {
- depth = overlap4;
- depth2 = overlap4;
- minIndex = 3;
- right = right4;
- }
- if (overlap5 > depth2) {
- depth = overlap5;
- depth2 = overlap5;
- minIndex = 4;
- right = right5;
- }
- if (overlap6 > depth2) {
- depth = overlap6;
- depth2 = overlap6;
- minIndex = 5;
- right = right6;
- }
- if (overlap7 - 0.01 > depth2 && !invalid7) {
- depth = overlap7;
- depth2 = overlap7 - 0.01;
- minIndex = 6;
- right = right7;
- }
- if (overlap8 - 0.01 > depth2 && !invalid8) {
- depth = overlap8;
- depth2 = overlap8 - 0.01;
- minIndex = 7;
- right = right8;
- }
- if (overlap9 - 0.01 > depth2 && !invalid9) {
- depth = overlap9;
- depth2 = overlap9 - 0.01;
- minIndex = 8;
- right = right9;
- }
- if (overlapa - 0.01 > depth2 && !invalida) {
- depth = overlapa;
- depth2 = overlapa - 0.01;
- minIndex = 9;
- right = righta;
- }
- if (overlapb - 0.01 > depth2 && !invalidb) {
- depth = overlapb;
- depth2 = overlapb - 0.01;
- minIndex = 10;
- right = rightb;
- }
- if (overlapc - 0.01 > depth2 && !invalidc) {
- depth = overlapc;
- depth2 = overlapc - 0.01;
- minIndex = 11;
- right = rightc;
- }
- if (overlapd - 0.01 > depth2 && !invalidd) {
- depth = overlapd;
- depth2 = overlapd - 0.01;
- minIndex = 12;
- right = rightd;
- }
- if (overlape - 0.01 > depth2 && !invalide) {
- depth = overlape;
- depth2 = overlape - 0.01;
- minIndex = 13;
- right = righte;
- }
- if (overlapf - 0.01 > depth2 && !invalidf) {
- depth = overlapf;
- minIndex = 14;
- right = rightf;
- }
- // normal
- var nx = 0;
- var ny = 0;
- var nz = 0;
- // edge line or face side normal
- var n1x = 0;
- var n1y = 0;
- var n1z = 0;
- var n2x = 0;
- var n2y = 0;
- var n2z = 0;
- // center of current face
- var cx = 0;
- var cy = 0;
- var cz = 0;
- // face side
- var s1x = 0;
- var s1y = 0;
- var s1z = 0;
- var s2x = 0;
- var s2y = 0;
- var s2z = 0;
- // swap b1 b2
- var swap = false;
- //_______________________________________
- if (minIndex == 0) {// b1.x * b2
- if (right) {
- cx = p1x + d1x; cy = p1y + d1y; cz = p1z + d1z;
- nx = a1x; ny = a1y; nz = a1z;
- } else {
- cx = p1x - d1x; cy = p1y - d1y; cz = p1z - d1z;
- nx = -a1x; ny = -a1y; nz = -a1z;
- }
- s1x = d2x; s1y = d2y; s1z = d2z;
- n1x = -a2x; n1y = -a2y; n1z = -a2z;
- s2x = d3x; s2y = d3y; s2z = d3z;
- n2x = -a3x; n2y = -a3y; n2z = -a3z;
- }
- else if (minIndex == 1) {// b1.y * b2
- if (right) {
- cx = p1x + d2x; cy = p1y + d2y; cz = p1z + d2z;
- nx = a2x; ny = a2y; nz = a2z;
- } else {
- cx = p1x - d2x; cy = p1y - d2y; cz = p1z - d2z;
- nx = -a2x; ny = -a2y; nz = -a2z;
- }
- s1x = d1x; s1y = d1y; s1z = d1z;
- n1x = -a1x; n1y = -a1y; n1z = -a1z;
- s2x = d3x; s2y = d3y; s2z = d3z;
- n2x = -a3x; n2y = -a3y; n2z = -a3z;
- }
- else if (minIndex == 2) {// b1.z * b2
- if (right) {
- cx = p1x + d3x; cy = p1y + d3y; cz = p1z + d3z;
- nx = a3x; ny = a3y; nz = a3z;
- } else {
- cx = p1x - d3x; cy = p1y - d3y; cz = p1z - d3z;
- nx = -a3x; ny = -a3y; nz = -a3z;
- }
- s1x = d1x; s1y = d1y; s1z = d1z;
- n1x = -a1x; n1y = -a1y; n1z = -a1z;
- s2x = d2x; s2y = d2y; s2z = d2z;
- n2x = -a2x; n2y = -a2y; n2z = -a2z;
- }
- else if (minIndex == 3) {// b2.x * b1
- swap = true;
- if (!right) {
- cx = p2x + d4x; cy = p2y + d4y; cz = p2z + d4z;
- nx = a4x; ny = a4y; nz = a4z;
- } else {
- cx = p2x - d4x; cy = p2y - d4y; cz = p2z - d4z;
- nx = -a4x; ny = -a4y; nz = -a4z;
- }
- s1x = d5x; s1y = d5y; s1z = d5z;
- n1x = -a5x; n1y = -a5y; n1z = -a5z;
- s2x = d6x; s2y = d6y; s2z = d6z;
- n2x = -a6x; n2y = -a6y; n2z = -a6z;
- }
- else if (minIndex == 4) {// b2.y * b1
- swap = true;
- if (!right) {
- cx = p2x + d5x; cy = p2y + d5y; cz = p2z + d5z;
- nx = a5x; ny = a5y; nz = a5z;
- } else {
- cx = p2x - d5x; cy = p2y - d5y; cz = p2z - d5z;
- nx = -a5x; ny = -a5y; nz = -a5z;
- }
- s1x = d4x; s1y = d4y; s1z = d4z;
- n1x = -a4x; n1y = -a4y; n1z = -a4z;
- s2x = d6x; s2y = d6y; s2z = d6z;
- n2x = -a6x; n2y = -a6y; n2z = -a6z;
- }
- else if (minIndex == 5) {// b2.z * b1
- swap = true;
- if (!right) {
- cx = p2x + d6x; cy = p2y + d6y; cz = p2z + d6z;
- nx = a6x; ny = a6y; nz = a6z;
- } else {
- cx = p2x - d6x; cy = p2y - d6y; cz = p2z - d6z;
- nx = -a6x; ny = -a6y; nz = -a6z;
- }
- s1x = d4x; s1y = d4y; s1z = d4z;
- n1x = -a4x; n1y = -a4y; n1z = -a4z;
- s2x = d5x; s2y = d5y; s2z = d5z;
- n2x = -a5x; n2y = -a5y; n2z = -a5z;
- }
- else if (minIndex == 6) {// b1.x * b2.x
- nx = a7x; ny = a7y; nz = a7z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a4x; n2y = a4y; n2z = a4z;
- }
- else if (minIndex == 7) {// b1.x * b2.y
- nx = a8x; ny = a8y; nz = a8z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 8) {// b1.x * b2.z
- nx = a9x; ny = a9y; nz = a9z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- else if (minIndex == 9) {// b1.y * b2.x
- nx = aax; ny = aay; nz = aaz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a4x; n2y = a4y; n2z = a4z
- }
- else if (minIndex == 10) {// b1.y * b2.y
- nx = abx; ny = aby; nz = abz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 11) {// b1.y * b2.z
- nx = acx; ny = acy; nz = acz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- else if (minIndex == 12) {// b1.z * b2.x
- nx = adx; ny = ady; nz = adz;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a4x; n2y = a4y; n2z = a4z;
- }
- else if (minIndex == 13) {// b1.z * b2.y
- nx = aex; ny = aey; nz = aez;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 14) {// b1.z * b2.z
- nx = afx; ny = afy; nz = afz;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- //__________________________________________
- var v;
- if (minIndex > 5) {
- if (!right) {
- nx = -nx; ny = -ny; nz = -nz;
- }
- var distance;
- var maxDistance;
- var vx;
- var vy;
- var vz;
- var v1x;
- var v1y;
- var v1z;
- var v2x;
- var v2y;
- var v2z;
- //vertex1;
- v1x = V1[0]; v1y = V1[1]; v1z = V1[2];
- maxDistance = nx * v1x + ny * v1y + nz * v1z;
- //vertex2;
- vx = V1[3]; vy = V1[4]; vz = V1[5];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex3;
- vx = V1[6]; vy = V1[7]; vz = V1[8];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex4;
- vx = V1[9]; vy = V1[10]; vz = V1[11];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex5;
- vx = V1[12]; vy = V1[13]; vz = V1[14];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex6;
- vx = V1[15]; vy = V1[16]; vz = V1[17];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex7;
- vx = V1[18]; vy = V1[19]; vz = V1[20];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex8;
- vx = V1[21]; vy = V1[22]; vz = V1[23];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex1;
- v2x = V2[0]; v2y = V2[1]; v2z = V2[2];
- maxDistance = nx * v2x + ny * v2y + nz * v2z;
- //vertex2;
- vx = V2[3]; vy = V2[4]; vz = V2[5];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex3;
- vx = V2[6]; vy = V2[7]; vz = V2[8];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex4;
- vx = V2[9]; vy = V2[10]; vz = V2[11];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex5;
- vx = V2[12]; vy = V2[13]; vz = V2[14];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex6;
- vx = V2[15]; vy = V2[16]; vz = V2[17];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex7;
- vx = V2[18]; vy = V2[19]; vz = V2[20];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex8;
- vx = V2[21]; vy = V2[22]; vz = V2[23];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- vx = v2x - v1x; vy = v2y - v1y; vz = v2z - v1z;
- dot1 = n1x * n2x + n1y * n2y + n1z * n2z;
- var t = (vx * (n1x - n2x * dot1) + vy * (n1y - n2y * dot1) + vz * (n1z - n2z * dot1)) / (1 - dot1 * dot1);
- manifold.addPoint(v1x + n1x * t + nx * depth * 0.5, v1y + n1y * t + ny * depth * 0.5, v1z + n1z * t + nz * depth * 0.5, nx, ny, nz, depth, false);
- return;
- }
- // now detect face-face collision...
- // target quad
- var q1x;
- var q1y;
- var q1z;
- var q2x;
- var q2y;
- var q2z;
- var q3x;
- var q3y;
- var q3z;
- var q4x;
- var q4y;
- var q4z;
- // search support face and vertex
- var minDot = 1;
- var dot = 0;
- var minDotIndex = 0;
- if (swap) {
- dot = a1x * nx + a1y * ny + a1z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 0;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 1;
- }
- dot = a2x * nx + a2y * ny + a2z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 2;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 3;
- }
- dot = a3x * nx + a3y * ny + a3z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 4;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 5;
- }
- if (minDotIndex == 0) {// x+ face
- q1x = V1[0]; q1y = V1[1]; q1z = V1[2];//vertex1
- q2x = V1[6]; q2y = V1[7]; q2z = V1[8];//vertex3
- q3x = V1[9]; q3y = V1[10]; q3z = V1[11];//vertex4
- q4x = V1[3]; q4y = V1[4]; q4z = V1[5];//vertex2
- }
- else if (minDotIndex == 1) {// x- face
- q1x = V1[15]; q1y = V1[16]; q1z = V1[17];//vertex6
- q2x = V1[21]; q2y = V1[22]; q2z = V1[23];//vertex8
- q3x = V1[18]; q3y = V1[19]; q3z = V1[20];//vertex7
- q4x = V1[12]; q4y = V1[13]; q4z = V1[14];//vertex5
- }
- else if (minDotIndex == 2) {// y+ face
- q1x = V1[12]; q1y = V1[13]; q1z = V1[14];//vertex5
- q2x = V1[0]; q2y = V1[1]; q2z = V1[2];//vertex1
- q3x = V1[3]; q3y = V1[4]; q3z = V1[5];//vertex2
- q4x = V1[15]; q4y = V1[16]; q4z = V1[17];//vertex6
- }
- else if (minDotIndex == 3) {// y- face
- q1x = V1[21]; q1y = V1[22]; q1z = V1[23];//vertex8
- q2x = V1[9]; q2y = V1[10]; q2z = V1[11];//vertex4
- q3x = V1[6]; q3y = V1[7]; q3z = V1[8];//vertex3
- q4x = V1[18]; q4y = V1[19]; q4z = V1[20];//vertex7
- }
- else if (minDotIndex == 4) {// z+ face
- q1x = V1[12]; q1y = V1[13]; q1z = V1[14];//vertex5
- q2x = V1[18]; q2y = V1[19]; q2z = V1[20];//vertex7
- q3x = V1[6]; q3y = V1[7]; q3z = V1[8];//vertex3
- q4x = V1[0]; q4y = V1[1]; q4z = V1[2];//vertex1
- }
- else if (minDotIndex == 5) {// z- face
- q1x = V1[3]; q1y = V1[4]; q1z = V1[5];//vertex2
- q2x = V1[6]; q2y = V1[7]; q2z = V1[8];//vertex4
- q3x = V1[21]; q3y = V1[22]; q3z = V1[23];//vertex8
- q4x = V1[15]; q4y = V1[16]; q4z = V1[17];//vertex6
- }
- } else {
- dot = a4x * nx + a4y * ny + a4z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 0;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 1;
- }
- dot = a5x * nx + a5y * ny + a5z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 2;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 3;
- }
- dot = a6x * nx + a6y * ny + a6z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 4;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 5;
- }
- //______________________________________________________
- if (minDotIndex == 0) {// x+ face
- q1x = V2[0]; q1y = V2[1]; q1z = V2[2];//vertex1
- q2x = V2[6]; q2y = V2[7]; q2z = V2[8];//vertex3
- q3x = V2[9]; q3y = V2[10]; q3z = V2[11];//vertex4
- q4x = V2[3]; q4y = V2[4]; q4z = V2[5];//vertex2
- }
- else if (minDotIndex == 1) {// x- face
- q1x = V2[15]; q1y = V2[16]; q1z = V2[17];//vertex6
- q2x = V2[21]; q2y = V2[22]; q2z = V2[23]; //vertex8
- q3x = V2[18]; q3y = V2[19]; q3z = V2[20];//vertex7
- q4x = V2[12]; q4y = V2[13]; q4z = V2[14];//vertex5
- }
- else if (minDotIndex == 2) {// y+ face
- q1x = V2[12]; q1y = V2[13]; q1z = V2[14];//vertex5
- q2x = V2[0]; q2y = V2[1]; q2z = V2[2];//vertex1
- q3x = V2[3]; q3y = V2[4]; q3z = V2[5];//vertex2
- q4x = V2[15]; q4y = V2[16]; q4z = V2[17];//vertex6
- }
- else if (minDotIndex == 3) {// y- face
- q1x = V2[21]; q1y = V2[22]; q1z = V2[23];//vertex8
- q2x = V2[9]; q2y = V2[10]; q2z = V2[11];//vertex4
- q3x = V2[6]; q3y = V2[7]; q3z = V2[8];//vertex3
- q4x = V2[18]; q4y = V2[19]; q4z = V2[20];//vertex7
- }
- else if (minDotIndex == 4) {// z+ face
- q1x = V2[12]; q1y = V2[13]; q1z = V2[14];//vertex5
- q2x = V2[18]; q2y = V2[19]; q2z = V2[20];//vertex7
- q3x = V2[6]; q3y = V2[7]; q3z = V2[8];//vertex3
- q4x = V2[0]; q4y = V2[1]; q4z = V2[2];//vertex1
- }
- else if (minDotIndex == 5) {// z- face
- q1x = V2[3]; q1y = V2[4]; q1z = V2[5];//vertex2
- q2x = V2[9]; q2y = V2[10]; q2z = V2[11];//vertex4
- q3x = V2[21]; q3y = V2[22]; q3z = V2[23];//vertex8
- q4x = V2[15]; q4y = V2[16]; q4z = V2[17];//vertex6
- }
- }
- // clip vertices
- var numClipVertices;
- var numAddedClipVertices;
- var index;
- var x1;
- var y1;
- var z1;
- var x2;
- var y2;
- var z2;
- this.clipVertices1[0] = q1x;
- this.clipVertices1[1] = q1y;
- this.clipVertices1[2] = q1z;
- this.clipVertices1[3] = q2x;
- this.clipVertices1[4] = q2y;
- this.clipVertices1[5] = q2z;
- this.clipVertices1[6] = q3x;
- this.clipVertices1[7] = q3y;
- this.clipVertices1[8] = q3z;
- this.clipVertices1[9] = q4x;
- this.clipVertices1[10] = q4y;
- this.clipVertices1[11] = q4z;
- numAddedClipVertices = 0;
- x1 = this.clipVertices1[9];
- y1 = this.clipVertices1[10];
- z1 = this.clipVertices1[11];
- dot1 = (x1 - cx - s1x) * n1x + (y1 - cy - s1y) * n1y + (z1 - cz - s1z) * n1z;
- //var i = 4;
- //while(i--){
- for (var i = 0; i < 4; i++) {
- index = i * 3;
- x2 = this.clipVertices1[index];
- y2 = this.clipVertices1[index + 1];
- z2 = this.clipVertices1[index + 2];
- dot2 = (x2 - cx - s1x) * n1x + (y2 - cy - s1y) * n1y + (z2 - cz - s1z) * n1z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices2[index];
- y1 = this.clipVertices2[index + 1];
- z1 = this.clipVertices2[index + 2];
- dot1 = (x1 - cx - s2x) * n2x + (y1 - cy - s2y) * n2y + (z1 - cz - s2z) * n2z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices2[index];
- y2 = this.clipVertices2[index + 1];
- z2 = this.clipVertices2[index + 2];
- dot2 = (x2 - cx - s2x) * n2x + (y2 - cy - s2y) * n2y + (z2 - cz - s2z) * n2z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot1 = (x1 - cx + s1x) * -n1x + (y1 - cy + s1y) * -n1y + (z1 - cz + s1z) * -n1z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices1[index];
- y2 = this.clipVertices1[index + 1];
- z2 = this.clipVertices1[index + 2];
- dot2 = (x2 - cx + s1x) * -n1x + (y2 - cy + s1y) * -n1y + (z2 - cz + s1z) * -n1z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices2[index];
- y1 = this.clipVertices2[index + 1];
- z1 = this.clipVertices2[index + 2];
- dot1 = (x1 - cx + s2x) * -n2x + (y1 - cy + s2y) * -n2y + (z1 - cz + s2z) * -n2z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices2[index];
- y2 = this.clipVertices2[index + 1];
- z2 = this.clipVertices2[index + 2];
- dot2 = (x2 - cx + s2x) * -n2x + (y2 - cy + s2y) * -n2y + (z2 - cz + s2z) * -n2z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (swap) {
- var tb = b1;
- b1 = b2;
- b2 = tb;
- }
- if (numClipVertices == 0) return;
- var flipped = b1 != shape1;
- if (numClipVertices > 4) {
- x1 = (q1x + q2x + q3x + q4x) * 0.25;
- y1 = (q1y + q2y + q3y + q4y) * 0.25;
- z1 = (q1z + q2z + q3z + q4z) * 0.25;
- n1x = q1x - x1;
- n1y = q1y - y1;
- n1z = q1z - z1;
- n2x = q2x - x1;
- n2y = q2y - y1;
- n2z = q2z - z1;
- var index1 = 0;
- var index2 = 0;
- var index3 = 0;
- var index4 = 0;
- var maxDot = -this.INF;
- minDot = this.INF;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- this.used[i] = false;
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = x1 * n1x + y1 * n1y + z1 * n1z;
- if (dot < minDot) {
- minDot = dot;
- index1 = i;
- }
- if (dot > maxDot) {
- maxDot = dot;
- index3 = i;
- }
- }
- this.used[index1] = true;
- this.used[index3] = true;
- maxDot = -this.INF;
- minDot = this.INF;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- if (this.used[i]) continue;
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = x1 * n2x + y1 * n2y + z1 * n2z;
- if (dot < minDot) {
- minDot = dot;
- index2 = i;
- }
- if (dot > maxDot) {
- maxDot = dot;
- index4 = i;
- }
- }
- index = index1 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index2 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index3 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index4 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- } else {
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- }
- }
- };
- /**
- * A collision detector which detects collisions between sphere and box.
- * @author saharan
- */
- OIMO.SphereBoxCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.SphereBoxCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereBoxCollisionDetector.prototype.constructor = OIMO.SphereBoxCollisionDetector;
- OIMO.SphereBoxCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s;
- var b;
- if (this.flip) {
- s = (shape2);
- b = (shape1);
- } else {
- s = (shape1);
- b = (shape2);
- }
- var D = b.dimentions;
- var ps = s.position;
- var psx = ps.x;
- var psy = ps.y;
- var psz = ps.z;
- var pb = b.position;
- var pbx = pb.x;
- var pby = pb.y;
- var pbz = pb.z;
- var rad = s.radius;
- var hw = b.halfWidth;
- var hh = b.halfHeight;
- var hd = b.halfDepth;
- var dx = psx - pbx;
- var dy = psy - pby;
- var dz = psz - pbz;
- var sx = D[0] * dx + D[1] * dy + D[2] * dz;
- var sy = D[3] * dx + D[4] * dy + D[5] * dz;
- var sz = D[6] * dx + D[7] * dy + D[8] * dz;
- var cx;
- var cy;
- var cz;
- var len;
- var invLen;
- var overlap = 0;
- if (sx > hw) {
- sx = hw;
- } else if (sx < -hw) {
- sx = -hw;
- } else {
- overlap = 1;
- }
- if (sy > hh) {
- sy = hh;
- } else if (sy < -hh) {
- sy = -hh;
- } else {
- overlap |= 2;
- }
- if (sz > hd) {
- sz = hd;
- } else if (sz < -hd) {
- sz = -hd;
- } else {
- overlap |= 4;
- }
- if (overlap == 7) {
- // center of sphere is in the box
- if (sx < 0) {
- dx = hw + sx;
- } else {
- dx = hw - sx;
- }
- if (sy < 0) {
- dy = hh + sy;
- } else {
- dy = hh - sy;
- }
- if (sz < 0) {
- dz = hd + sz;
- } else {
- dz = hd - sz;
- }
- if (dx < dy) {
- if (dx < dz) {
- len = dx - hw;
- if (sx < 0) {
- sx = -hw;
- dx = D[0];
- dy = D[1];
- dz = D[2];
- } else {
- sx = hw;
- dx = -D[0];
- dy = -D[1];
- dz = -D[2];
- }
- } else {
- len = dz - hd;
- if (sz < 0) {
- sz = -hd;
- dx = D[6];
- dy = D[7];
- dz = D[8];
- } else {
- sz = hd;
- dx = -D[6];
- dy = -D[7];
- dz = -D[8];
- }
- }
- } else {
- if (dy < dz) {
- len = dy - hh;
- if (sy < 0) {
- sy = -hh;
- dx = D[3];
- dy = D[4];
- dz = D[5];
- } else {
- sy = hh;
- dx = -D[3];
- dy = -D[4];
- dz = -D[5];
- }
- } else {
- len = dz - hd;
- if (sz < 0) {
- sz = -hd;
- dx = D[6];
- dy = D[7];
- dz = D[8];
- } else {
- sz = hd;
- dx = -D[6];
- dy = -D[7];
- dz = -D[8];
- }
- }
- }
- cx = pbx + sx * D[0] + sy * D[3] + sz * D[6];
- cy = pby + sx * D[1] + sy * D[4] + sz * D[7];
- cz = pbz + sx * D[2] + sy * D[5] + sz * D[8];
- manifold.addPoint(psx + rad * dx, psy + rad * dy, psz + rad * dz, dx, dy, dz, len - rad, this.flip);
- } else {
- cx = pbx + sx * D[0] + sy * D[3] + sz * D[6];
- cy = pby + sx * D[1] + sy * D[4] + sz * D[7];
- cz = pbz + sx * D[2] + sy * D[5] + sz * D[8];
- dx = cx - ps.x;
- dy = cy - ps.y;
- dz = cz - ps.z;
- len = dx * dx + dy * dy + dz * dz;
- if (len > 0 && len < rad * rad) {
- len = OIMO.sqrt(len);
- invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- manifold.addPoint(psx + rad * dx, psy + rad * dy, psz + rad * dz, dx, dy, dz, len - rad, this.flip);
- }
- }
- };
- /**
- * A collision detector which detects collisions between two spheres.
- * @author saharan
- */
- OIMO.SphereSphereCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.SphereSphereCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereSphereCollisionDetector.prototype.constructor = OIMO.SphereSphereCollisionDetector;
- OIMO.SphereSphereCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s1 = shape1;
- var s2 = shape2;
- var p1 = s1.position;
- var p2 = s2.position;
- var dx = p2.x - p1.x;
- var dy = p2.y - p1.y;
- var dz = p2.z - p1.z;
- var len = dx * dx + dy * dy + dz * dz;
- var r1 = s1.radius;
- var r2 = s2.radius;
- var rad = r1 + r2;
- if (len > 0 && len < rad * rad) {
- len = OIMO.sqrt(len);
- var invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- manifold.addPoint(p1.x + dx * r1, p1.y + dy * r1, p1.z + dz * r1, dx, dy, dz, len - rad, false);
- }
- };
- OIMO.BoxCylinderCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.BoxCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.BoxCylinderCollisionDetector.prototype.constructor = OIMO.BoxCylinderCollisionDetector;
- OIMO.BoxCylinderCollisionDetector.prototype.getSep = function (c1, c2, sep, pos, dep) {
- var t1x;
- var t1y;
- var t1z;
- var t2x;
- var t2y;
- var t2z;
- var sup = new OIMO.Vec3();
- var len;
- var p1x;
- var p1y;
- var p1z;
- var p2x;
- var p2y;
- var p2z;
- var v01x = c1.position.x;
- var v01y = c1.position.y;
- var v01z = c1.position.z;
- var v02x = c2.position.x;
- var v02y = c2.position.y;
- var v02z = c2.position.z;
- var v0x = v02x - v01x;
- var v0y = v02y - v01y;
- var v0z = v02z - v01z;
- if (v0x * v0x + v0y * v0y + v0z * v0z == 0) v0y = 0.001;
- var nx = -v0x;
- var ny = -v0y;
- var nz = -v0z;
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v11x = sup.x;
- var v11y = sup.y;
- var v11z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v12x = sup.x;
- var v12y = sup.y;
- var v12z = sup.z;
- var v1x = v12x - v11x;
- var v1y = v12y - v11y;
- var v1z = v12z - v11z;
- if (v1x * nx + v1y * ny + v1z * nz <= 0) {
- return false;
- }
- nx = v1y * v0z - v1z * v0y;
- ny = v1z * v0x - v1x * v0z;
- nz = v1x * v0y - v1y * v0x;
- if (nx * nx + ny * ny + nz * nz == 0) {
- sep.init(v1x - v0x, v1y - v0y, v1z - v0z);
- sep.normalize(sep);
- pos.init((v11x + v12x) * 0.5, (v11y + v12y) * 0.5, (v11z + v12z) * 0.5);
- return true;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v21x = sup.x;
- var v21y = sup.y;
- var v21z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v22x = sup.x;
- var v22y = sup.y;
- var v22z = sup.z;
- var v2x = v22x - v21x;
- var v2y = v22y - v21y;
- var v2z = v22z - v21z;
- if (v2x * nx + v2y * ny + v2z * nz <= 0) {
- return false;
- }
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- if (nx * v0x + ny * v0y + nz * v0z > 0) {
- t1x = v1x;
- t1y = v1y;
- t1z = v1z;
- v1x = v2x;
- v1y = v2y;
- v1z = v2z;
- v2x = t1x;
- v2y = t1y;
- v2z = t1z;
- t1x = v11x;
- t1y = v11y;
- t1z = v11z;
- v11x = v21x;
- v11y = v21y;
- v11z = v21z;
- v21x = t1x;
- v21y = t1y;
- v21z = t1z;
- t1x = v12x;
- t1y = v12y;
- t1z = v12z;
- v12x = v22x;
- v12y = v22y;
- v12z = v22z;
- v22x = t1x;
- v22y = t1y;
- v22z = t1z;
- nx = -nx;
- ny = -ny;
- nz = -nz;
- }
- var iterations = 0;
- while (true) {
- if (++iterations > 100) {
- return false;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v31x = sup.x;
- var v31y = sup.y;
- var v31z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v32x = sup.x;
- var v32y = sup.y;
- var v32z = sup.z;
- var v3x = v32x - v31x;
- var v3y = v32y - v31y;
- var v3z = v32z - v31z;
- if (v3x * nx + v3y * ny + v3z * nz <= 0) {
- return false;
- }
- if ((v1y * v3z - v1z * v3y) * v0x + (v1z * v3x - v1x * v3z) * v0y + (v1x * v3y - v1y * v3x) * v0z < 0) {
- v2x = v3x;
- v2y = v3y;
- v2z = v3z;
- v21x = v31x;
- v21y = v31y;
- v21z = v31z;
- v22x = v32x;
- v22y = v32y;
- v22z = v32z;
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v3x - v0x;
- t2y = v3y - v0y;
- t2z = v3z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- if ((v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z < 0) {
- v1x = v3x;
- v1y = v3y;
- v1z = v3z;
- v11x = v31x;
- v11y = v31y;
- v11z = v31z;
- v12x = v32x;
- v12y = v32y;
- v12z = v32z;
- t1x = v3x - v0x;
- t1y = v3y - v0y;
- t1z = v3z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- var hit = false;
- while (true) {
- t1x = v2x - v1x;
- t1y = v2y - v1y;
- t1z = v2z - v1z;
- t2x = v3x - v1x;
- t2y = v3y - v1y;
- t2z = v3z - v1z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- len = 1 / OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- nx *= len;
- ny *= len;
- nz *= len;
- if (nx * v1x + ny * v1y + nz * v1z >= 0 && !hit) {
- var b0 = (v1y * v2z - v1z * v2y) * v3x + (v1z * v2x - v1x * v2z) * v3y + (v1x * v2y - v1y * v2x) * v3z;
- var b1 = (v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z;
- var b2 = (v0y * v1z - v0z * v1y) * v3x + (v0z * v1x - v0x * v1z) * v3y + (v0x * v1y - v0y * v1x) * v3z;
- var b3 = (v2y * v1z - v2z * v1y) * v0x + (v2z * v1x - v2x * v1z) * v0y + (v2x * v1y - v2y * v1x) * v0z;
- var sum = b0 + b1 + b2 + b3;
- if (sum <= 0) {
- b0 = 0;
- b1 = (v2y * v3z - v2z * v3y) * nx + (v2z * v3x - v2x * v3z) * ny + (v2x * v3y - v2y * v3x) * nz;
- b2 = (v3y * v2z - v3z * v2y) * nx + (v3z * v2x - v3x * v2z) * ny + (v3x * v2y - v3y * v2x) * nz;
- b3 = (v1y * v2z - v1z * v2y) * nx + (v1z * v2x - v1x * v2z) * ny + (v1x * v2y - v1y * v2x) * nz;
- sum = b1 + b2 + b3;
- }
- var inv = 1 / sum;
- p1x = (v01x * b0 + v11x * b1 + v21x * b2 + v31x * b3) * inv;
- p1y = (v01y * b0 + v11y * b1 + v21y * b2 + v31y * b3) * inv;
- p1z = (v01z * b0 + v11z * b1 + v21z * b2 + v31z * b3) * inv;
- p2x = (v02x * b0 + v12x * b1 + v22x * b2 + v32x * b3) * inv;
- p2y = (v02y * b0 + v12y * b1 + v22y * b2 + v32y * b3) * inv;
- p2z = (v02z * b0 + v12z * b1 + v22z * b2 + v32z * b3) * inv;
- hit = true;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v41x = sup.x;
- var v41y = sup.y;
- var v41z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v42x = sup.x;
- var v42y = sup.y;
- var v42z = sup.z;
- var v4x = v42x - v41x;
- var v4y = v42y - v41y;
- var v4z = v42z - v41z;
- var separation = -(v4x * nx + v4y * ny + v4z * nz);
- if ((v4x - v3x) * nx + (v4y - v3y) * ny + (v4z - v3z) * nz <= 0.01 || separation >= 0) {
- if (hit) {
- sep.init(-nx, -ny, -nz);
- pos.init((p1x + p2x) * 0.5, (p1y + p2y) * 0.5, (p1z + p2z) * 0.5);
- dep.x = separation;
- return true;
- }
- return false;
- }
- if (
- (v4y * v1z - v4z * v1y) * v0x +
- (v4z * v1x - v4x * v1z) * v0y +
- (v4x * v1y - v4y * v1x) * v0z < 0
- ) {
- if (
- (v4y * v2z - v4z * v2y) * v0x +
- (v4z * v2x - v4x * v2z) * v0y +
- (v4x * v2y - v4y * v2x) * v0z < 0
- ) {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- } else {
- v3x = v4x;
- v3y = v4y;
- v3z = v4z;
- v31x = v41x;
- v31y = v41y;
- v31z = v41z;
- v32x = v42x;
- v32y = v42y;
- v32z = v42z;
- }
- } else {
- if (
- (v4y * v3z - v4z * v3y) * v0x +
- (v4z * v3x - v4x * v3z) * v0y +
- (v4x * v3y - v4y * v3x) * v0z < 0
- ) {
- v2x = v4x;
- v2y = v4y;
- v2z = v4z;
- v21x = v41x;
- v21y = v41y;
- v21z = v41z;
- v22x = v42x;
- v22y = v42y;
- v22z = v42z;
- } else {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- }
- }
- }
- }
- //return false;
- };
- OIMO.BoxCylinderCollisionDetector.prototype.supportPointB = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var w = c.halfWidth;
- var h = c.halfHeight;
- var d = c.halfDepth;
- var ox;
- var oy;
- var oz;
- if (ldx < 0) ox = -w;
- else ox = w;
- if (ldy < 0) oy = -h;
- else oy = h;
- if (ldz < 0) oz = -d;
- else oz = d;
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.BoxCylinderCollisionDetector.prototype.supportPointC = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var radx = ldx;
- var radz = ldz;
- var len = radx * radx + radz * radz;
- var rad = c.radius;
- var hh = c.halfHeight;
- var ox;
- var oy;
- var oz;
- if (len == 0) {
- if (ldy < 0) {
- ox = rad;
- oy = -hh;
- oz = 0;
- } else {
- ox = rad;
- oy = hh;
- oz = 0;
- }
- } else {
- len = c.radius / OIMO.sqrt(len);
- if (ldy < 0) {
- ox = radx * len;
- oy = -hh;
- oz = radz * len;
- } else {
- ox = radx * len;
- oy = hh;
- oz = radz * len;
- }
- }
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.BoxCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var b;
- var c;
- if (this.flip) {
- b = shape2;
- c = shape1;
- } else {
- b = shape1;
- c = shape2;
- }
- var sep = new OIMO.Vec3();
- var pos = new OIMO.Vec3();
- var dep = new OIMO.Vec3();
- var co;
- if (!this.getSep(b, c, sep, pos, dep)) return;
- var pbx = b.position.x;
- var pby = b.position.y;
- var pbz = b.position.z;
- var pcx = c.position.x;
- var pcy = c.position.y;
- var pcz = c.position.z;
- var bw = b.halfWidth;
- var bh = b.halfHeight;
- var bd = b.halfDepth;
- var ch = c.halfHeight;
- var r = c.radius;
- var D = b.dimentions;
- var nwx = D[0];//b.normalDirectionWidth.x;
- var nwy = D[1];//b.normalDirectionWidth.y;
- var nwz = D[2];//b.normalDirectionWidth.z;
- var nhx = D[3];//b.normalDirectionHeight.x;
- var nhy = D[4];//b.normalDirectionHeight.y;
- var nhz = D[5];//b.normalDirectionHeight.z;
- var ndx = D[6];//b.normalDirectionDepth.x;
- var ndy = D[7];//b.normalDirectionDepth.y;
- var ndz = D[8];//b.normalDirectionDepth.z;
- var dwx = D[9];//b.halfDirectionWidth.x;
- var dwy = D[10];//b.halfDirectionWidth.y;
- var dwz = D[11];//b.halfDirectionWidth.z;
- var dhx = D[12];//b.halfDirectionHeight.x;
- var dhy = D[13];//b.halfDirectionHeight.y;
- var dhz = D[14];//b.halfDirectionHeight.z;
- var ddx = D[15];//b.halfDirectionDepth.x;
- var ddy = D[16];//b.halfDirectionDepth.y;
- var ddz = D[17];//b.halfDirectionDepth.z;
- var ncx = c.normalDirection.x;
- var ncy = c.normalDirection.y;
- var ncz = c.normalDirection.z;
- var dcx = c.halfDirection.x;
- var dcy = c.halfDirection.y;
- var dcz = c.halfDirection.z;
- var nx = sep.x;
- var ny = sep.y;
- var nz = sep.z;
- var dotw = nx * nwx + ny * nwy + nz * nwz;
- var doth = nx * nhx + ny * nhy + nz * nhz;
- var dotd = nx * ndx + ny * ndy + nz * ndz;
- var dotc = nx * ncx + ny * ncy + nz * ncz;
- var right1 = dotw > 0;
- var right2 = doth > 0;
- var right3 = dotd > 0;
- var right4 = dotc > 0;
- if (!right1) dotw = -dotw;
- if (!right2) doth = -doth;
- if (!right3) dotd = -dotd;
- if (!right4) dotc = -dotc;
- var state = 0;
- if (dotc > 0.999) {
- if (dotw > 0.999) {
- if (dotw > dotc) state = 1;
- else state = 4;
- } else if (doth > 0.999) {
- if (doth > dotc) state = 2;
- else state = 4;
- } else if (dotd > 0.999) {
- if (dotd > dotc) state = 3;
- else state = 4;
- } else state = 4;
- } else {
- if (dotw > 0.999) state = 1;
- else if (doth > 0.999) state = 2;
- else if (dotd > 0.999) state = 3;
- }
- var cbx;
- var cby;
- var cbz;
- var ccx;
- var ccy;
- var ccz;
- var r00;
- var r01;
- var r02;
- var r10;
- var r11;
- var r12;
- var r20;
- var r21;
- var r22;
- var px;
- var py;
- var pz;
- var pd;
- var dot;
- var len;
- var tx;
- var ty;
- var tz;
- var td;
- var dx;
- var dy;
- var dz;
- var d1x;
- var d1y;
- var d1z;
- var d2x;
- var d2y;
- var d2z;
- var sx;
- var sy;
- var sz;
- var sd;
- var ex;
- var ey;
- var ez;
- var ed;
- var dot1;
- var dot2;
- var t1;
- var t2;
- var dir1x;
- var dir1y;
- var dir1z;
- var dir2x;
- var dir2y;
- var dir2z;
- var dir1l;
- var dir2l;
- if (state == 0) {
- //manifold.addPoint(pos.x,pos.y,pos.z,nx,ny,nz,dep.x,b,c,0,0,false);
- manifold.addPoint(pos.x, pos.y, pos.z, nx, ny, nz, dep.x, this.flip);
- } else if (state == 4) {
- if (right4) {
- ccx = pcx - dcx;
- ccy = pcy - dcy;
- ccz = pcz - dcz;
- nx = -ncx;
- ny = -ncy;
- nz = -ncz;
- } else {
- ccx = pcx + dcx;
- ccy = pcy + dcy;
- ccz = pcz + dcz;
- nx = ncx;
- ny = ncy;
- nz = ncz;
- }
- var v1x;
- var v1y;
- var v1z;
- var v2x;
- var v2y;
- var v2z;
- var v3x;
- var v3y;
- var v3z;
- var v4x;
- var v4y;
- var v4z;
- dot = 1;
- state = 0;
- dot1 = nwx * nx + nwy * ny + nwz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 0;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 1;
- }
- dot1 = nhx * nx + nhy * ny + nhz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 2;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 3;
- }
- dot1 = ndx * nx + ndy * ny + ndz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 4;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 5;
- }
- var v = b.elements;
- switch (state) {
- case 0:
- //v=b.vertex1;
- v1x = v[0];//v.x;
- v1y = v[1];//v.y;
- v1z = v[2];//v.z;
- //v=b.vertex3;
- v2x = v[6];//v.x;
- v2y = v[7];//v.y;
- v2z = v[8];//v.z;
- //v=b.vertex4;
- v3x = v[9];//v.x;
- v3y = v[10];//v.y;
- v3z = v[11];//v.z;
- //v=b.vertex2;
- v4x = v[3];//v.x;
- v4y = v[4];//v.y;
- v4z = v[5];//v.z;
- break;
- case 1:
- //v=b.vertex6;
- v1x = v[15];//v.x;
- v1y = v[16];//v.y;
- v1z = v[17];//v.z;
- //v=b.vertex8;
- v2x = v[21];//v.x;
- v2y = v[22];//v.y;
- v2z = v[23];//v.z;
- //v=b.vertex7;
- v3x = v[18];//v.x;
- v3y = v[19];//v.y;
- v3z = v[20];//v.z;
- //v=b.vertex5;
- v4x = v[12];//v.x;
- v4y = v[13];//v.y;
- v4z = v[14];//v.z;
- break;
- case 2:
- //v=b.vertex5;
- v1x = v[12];//v.x;
- v1y = v[13];//v.y;
- v1z = v[14];//v.z;
- //v=b.vertex1;
- v2x = v[0];//v.x;
- v2y = v[1];//v.y;
- v2z = v[2];//v.z;
- //v=b.vertex2;
- v3x = v[3];//v.x;
- v3y = v[4];//v.y;
- v3z = v[5];//v.z;
- //v=b.vertex6;
- v4x = v[15];//v.x;
- v4y = v[16];//v.y;
- v4z = v[17];//v.z;
- break;
- case 3:
- //v=b.vertex8;
- v1x = v[21];//v.x;
- v1y = v[22];//v.y;
- v1z = v[23];//v.z;
- //v=b.vertex4;
- v2x = v[9];//v.x;
- v2y = v[10];//v.y;
- v2z = v[11];//v.z;
- //v=b.vertex3;
- v3x = v[6];//v.x;
- v3y = v[7];//v.y;
- v3z = v[8];//v.z;
- //v=b.vertex7;
- v4x = v[18];//v.x;
- v4y = v[19];//v.y;
- v4z = v[20];//v.z;
- break;
- case 4:
- //v=b.vertex5;
- v1x = v[12];//v.x;
- v1y = v[13];//v.y;
- v1z = v[14];//v.z;
- //v=b.vertex7;
- v2x = v[18];//v.x;
- v2y = v[19];//v.y;
- v2z = v[20];//v.z;
- //v=b.vertex3;
- v3x = v[6];//v.x;
- v3y = v[7];//v.y;
- v3z = v[8];//v.z;
- //v=b.vertex1;
- v4x = v[0];//v.x;
- v4y = v[1];//v.y;
- v4z = v[2];//v.z;
- break;
- case 5:
- //v=b.vertex2;
- v1x = v[3];//v.x;
- v1y = v[4];//v.y;
- v1z = v[5];//v.z;
- //v=b.vertex4;
- v2x = v[9];//v.x;
- v2y = v[10];//v.y;
- v2z = v[11];//v.z;
- //v=b.vertex8;
- v3x = v[21];//v.x;
- v3y = v[22];//v.y;
- v3z = v[23];//v.z;
- //v=b.vertex6;
- v4x = v[15];//v.x;
- v4y = v[16];//v.y;
- v4z = v[17];//v.z;
- break;
- }
- pd = nx * (v1x - ccx) + ny * (v1y - ccy) + nz * (v1z - ccz);
- if (pd <= 0) manifold.addPoint(v1x, v1y, v1z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v2x - ccx) + ny * (v2y - ccy) + nz * (v2z - ccz);
- if (pd <= 0) manifold.addPoint(v2x, v2y, v2z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v3x - ccx) + ny * (v3y - ccy) + nz * (v3z - ccz);
- if (pd <= 0) manifold.addPoint(v3x, v3y, v3z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v4x - ccx) + ny * (v4y - ccy) + nz * (v4z - ccz);
- if (pd <= 0) manifold.addPoint(v4x, v4y, v4z, -nx, -ny, -nz, pd, this.flip);
- } else {
- switch (state) {
- case 1:
- if (right1) {
- cbx = pbx + dwx;
- cby = pby + dwy;
- cbz = pbz + dwz;
- nx = nwx;
- ny = nwy;
- nz = nwz;
- } else {
- cbx = pbx - dwx;
- cby = pby - dwy;
- cbz = pbz - dwz;
- nx = -nwx;
- ny = -nwy;
- nz = -nwz;
- }
- dir1x = nhx;
- dir1y = nhy;
- dir1z = nhz;
- dir1l = bh;
- dir2x = ndx;
- dir2y = ndy;
- dir2z = ndz;
- dir2l = bd;
- break;
- case 2:
- if (right2) {
- cbx = pbx + dhx;
- cby = pby + dhy;
- cbz = pbz + dhz;
- nx = nhx;
- ny = nhy;
- nz = nhz;
- } else {
- cbx = pbx - dhx;
- cby = pby - dhy;
- cbz = pbz - dhz;
- nx = -nhx;
- ny = -nhy;
- nz = -nhz;
- }
- dir1x = nwx;
- dir1y = nwy;
- dir1z = nwz;
- dir1l = bw;
- dir2x = ndx;
- dir2y = ndy;
- dir2z = ndz;
- dir2l = bd;
- break;
- case 3:
- if (right3) {
- cbx = pbx + ddx;
- cby = pby + ddy;
- cbz = pbz + ddz;
- nx = ndx;
- ny = ndy;
- nz = ndz;
- } else {
- cbx = pbx - ddx;
- cby = pby - ddy;
- cbz = pbz - ddz;
- nx = -ndx;
- ny = -ndy;
- nz = -ndz;
- }
- dir1x = nwx;
- dir1y = nwy;
- dir1z = nwz;
- dir1l = bw;
- dir2x = nhx;
- dir2y = nhy;
- dir2z = nhz;
- dir2l = bh;
- break;
- }
- dot = nx * ncx + ny * ncy + nz * ncz;
- if (dot < 0) len = ch;
- else len = -ch;
- ccx = pcx + len * ncx;
- ccy = pcy + len * ncy;
- ccz = pcz + len * ncz;
- if (dotc >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * ncx + ty * ncy + tz * ncz;
- dx = len * ncx - tx;
- dy = len * ncy - ty;
- dz = len * ncz - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) return;
- len = r / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = ccx + dx;
- ty = ccy + dy;
- tz = ccz + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = ncx * ncx * 1.5 - 0.5;
- r01 = ncx * ncy * 1.5 - ncz * 0.866025403;
- r02 = ncx * ncz * 1.5 + ncy * 0.866025403;
- r10 = ncy * ncx * 1.5 + ncz * 0.866025403;
- r11 = ncy * ncy * 1.5 - 0.5;
- r12 = ncy * ncz * 1.5 - ncx * 0.866025403;
- r20 = ncz * ncx * 1.5 - ncy * 0.866025403;
- r21 = ncz * ncy * 1.5 + ncx * 0.866025403;
- r22 = ncz * ncz * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + ccx;
- py = (dy = py) + ccy;
- pz = (dz = pz) + ccz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- if (pd <= 0) {
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- //manifold.addPoint(px,py,pz,nx,ny,nz,pd,b,c,2,0,false);
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + ccx;
- py = (dy = py) + ccy;
- pz = (dz = pz) + ccz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- if (pd <= 0) {
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- //manifold.addPoint(px,py,pz,nx,ny,nz,pd,b,c,3,0,false);
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- sd = nx * (sx - cbx) + ny * (sy - cby) + nz * (sz - cbz);
- sx -= sd * nx;
- sy -= sd * ny;
- sz -= sd * nz;
- if (dot > 0) {
- ex = tx + dcx * 2;
- ey = ty + dcy * 2;
- ez = tz + dcz * 2;
- } else {
- ex = tx - dcx * 2;
- ey = ty - dcy * 2;
- ez = tz - dcz * 2;
- }
- ed = nx * (ex - cbx) + ny * (ey - cby) + nz * (ez - cbz);
- ex -= ed * nx;
- ey -= ed * ny;
- ez -= ed * nz;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- dotw = d1x * dir1x + d1y * dir1y + d1z * dir1z;
- doth = d2x * dir1x + d2y * dir1y + d2z * dir1z;
- dot1 = dotw - dir1l;
- dot2 = doth - dir1l;
- if (dot1 > 0) {
- if (dot2 > 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- dotw = d1x * dir1x + d1y * dir1y + d1z * dir1z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 > 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- doth = d2x * dir1x + d2y * dir1y + d2z * dir1z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dot1 = dotw + dir1l;
- dot2 = doth + dir1l;
- if (dot1 < 0) {
- if (dot2 < 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 < 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dotw = d1x * dir2x + d1y * dir2y + d1z * dir2z;
- doth = d2x * dir2x + d2y * dir2y + d2z * dir2z;
- dot1 = dotw - dir2l;
- dot2 = doth - dir2l;
- if (dot1 > 0) {
- if (dot2 > 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- dotw = d1x * dir2x + d1y * dir2y + d1z * dir2z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 > 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- doth = d2x * dir2x + d2y * dir2y + d2z * dir2z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dot1 = dotw + dir2l;
- dot2 = doth + dir2l;
- if (dot1 < 0) {
- if (dot2 < 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- } else if (dot2 < 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- }
- if (sd < 0) {
- //manifold.addPoint(sx,sy,sz,nx,ny,nz,sd,b,c,1,0,false);
- manifold.addPoint(sx, sy, sz, nx, ny, nz, sd, this.flip);
- }
- if (ed < 0) {
- //manifold.addPoint(ex,ey,ez,nx,ny,nz,ed,b,c,4,0,false);
- manifold.addPoint(ex, ey, ez, nx, ny, nz, ed, this.flip);
- }
- }
- }
- };
- OIMO.CylinderCylinderCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.CylinderCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.CylinderCylinderCollisionDetector.prototype.constructor = OIMO.CylinderCylinderCollisionDetector;
- OIMO.CylinderCylinderCollisionDetector.prototype.getSep = function (c1, c2, sep, pos, dep) {
- var t1x;
- var t1y;
- var t1z;
- var t2x;
- var t2y;
- var t2z;
- var sup = new OIMO.Vec3();
- var len;
- var p1x;
- var p1y;
- var p1z;
- var p2x;
- var p2y;
- var p2z;
- var v01x = c1.position.x;
- var v01y = c1.position.y;
- var v01z = c1.position.z;
- var v02x = c2.position.x;
- var v02y = c2.position.y;
- var v02z = c2.position.z;
- var v0x = v02x - v01x;
- var v0y = v02y - v01y;
- var v0z = v02z - v01z;
- if (v0x * v0x + v0y * v0y + v0z * v0z == 0) v0y = 0.001;
- var nx = -v0x;
- var ny = -v0y;
- var nz = -v0z;
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v11x = sup.x;
- var v11y = sup.y;
- var v11z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v12x = sup.x;
- var v12y = sup.y;
- var v12z = sup.z;
- var v1x = v12x - v11x;
- var v1y = v12y - v11y;
- var v1z = v12z - v11z;
- if (v1x * nx + v1y * ny + v1z * nz <= 0) {
- return false;
- }
- nx = v1y * v0z - v1z * v0y;
- ny = v1z * v0x - v1x * v0z;
- nz = v1x * v0y - v1y * v0x;
- if (nx * nx + ny * ny + nz * nz == 0) {
- sep.init(v1x - v0x, v1y - v0y, v1z - v0z);
- sep.normalize(sep);
- pos.init((v11x + v12x) * 0.5, (v11y + v12y) * 0.5, (v11z + v12z) * 0.5);
- return true;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v21x = sup.x;
- var v21y = sup.y;
- var v21z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v22x = sup.x;
- var v22y = sup.y;
- var v22z = sup.z;
- var v2x = v22x - v21x;
- var v2y = v22y - v21y;
- var v2z = v22z - v21z;
- if (v2x * nx + v2y * ny + v2z * nz <= 0) {
- return false;
- }
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- if (nx * v0x + ny * v0y + nz * v0z > 0) {
- t1x = v1x;
- t1y = v1y;
- t1z = v1z;
- v1x = v2x;
- v1y = v2y;
- v1z = v2z;
- v2x = t1x;
- v2y = t1y;
- v2z = t1z;
- t1x = v11x;
- t1y = v11y;
- t1z = v11z;
- v11x = v21x;
- v11y = v21y;
- v11z = v21z;
- v21x = t1x;
- v21y = t1y;
- v21z = t1z;
- t1x = v12x;
- t1y = v12y;
- t1z = v12z;
- v12x = v22x;
- v12y = v22y;
- v12z = v22z;
- v22x = t1x;
- v22y = t1y;
- v22z = t1z;
- nx = -nx;
- ny = -ny;
- nz = -nz;
- }
- var iterations = 0;
- while (true) {
- if (++iterations > 100) {
- return false;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v31x = sup.x;
- var v31y = sup.y;
- var v31z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v32x = sup.x;
- var v32y = sup.y;
- var v32z = sup.z;
- var v3x = v32x - v31x;
- var v3y = v32y - v31y;
- var v3z = v32z - v31z;
- if (v3x * nx + v3y * ny + v3z * nz <= 0) {
- return false;
- }
- if ((v1y * v3z - v1z * v3y) * v0x + (v1z * v3x - v1x * v3z) * v0y + (v1x * v3y - v1y * v3x) * v0z < 0) {
- v2x = v3x;
- v2y = v3y;
- v2z = v3z;
- v21x = v31x;
- v21y = v31y;
- v21z = v31z;
- v22x = v32x;
- v22y = v32y;
- v22z = v32z;
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v3x - v0x;
- t2y = v3y - v0y;
- t2z = v3z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- if ((v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z < 0) {
- v1x = v3x;
- v1y = v3y;
- v1z = v3z;
- v11x = v31x;
- v11y = v31y;
- v11z = v31z;
- v12x = v32x;
- v12y = v32y;
- v12z = v32z;
- t1x = v3x - v0x;
- t1y = v3y - v0y;
- t1z = v3z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- var hit = false;
- while (true) {
- t1x = v2x - v1x;
- t1y = v2y - v1y;
- t1z = v2z - v1z;
- t2x = v3x - v1x;
- t2y = v3y - v1y;
- t2z = v3z - v1z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- len = 1 / OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- nx *= len;
- ny *= len;
- nz *= len;
- if (nx * v1x + ny * v1y + nz * v1z >= 0 && !hit) {
- var b0 = (v1y * v2z - v1z * v2y) * v3x + (v1z * v2x - v1x * v2z) * v3y + (v1x * v2y - v1y * v2x) * v3z;
- var b1 = (v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z;
- var b2 = (v0y * v1z - v0z * v1y) * v3x + (v0z * v1x - v0x * v1z) * v3y + (v0x * v1y - v0y * v1x) * v3z;
- var b3 = (v2y * v1z - v2z * v1y) * v0x + (v2z * v1x - v2x * v1z) * v0y + (v2x * v1y - v2y * v1x) * v0z;
- var sum = b0 + b1 + b2 + b3;
- if (sum <= 0) {
- b0 = 0;
- b1 = (v2y * v3z - v2z * v3y) * nx + (v2z * v3x - v2x * v3z) * ny + (v2x * v3y - v2y * v3x) * nz;
- b2 = (v3y * v2z - v3z * v2y) * nx + (v3z * v2x - v3x * v2z) * ny + (v3x * v2y - v3y * v2x) * nz;
- b3 = (v1y * v2z - v1z * v2y) * nx + (v1z * v2x - v1x * v2z) * ny + (v1x * v2y - v1y * v2x) * nz;
- sum = b1 + b2 + b3;
- }
- var inv = 1 / sum;
- p1x = (v01x * b0 + v11x * b1 + v21x * b2 + v31x * b3) * inv;
- p1y = (v01y * b0 + v11y * b1 + v21y * b2 + v31y * b3) * inv;
- p1z = (v01z * b0 + v11z * b1 + v21z * b2 + v31z * b3) * inv;
- p2x = (v02x * b0 + v12x * b1 + v22x * b2 + v32x * b3) * inv;
- p2y = (v02y * b0 + v12y * b1 + v22y * b2 + v32y * b3) * inv;
- p2z = (v02z * b0 + v12z * b1 + v22z * b2 + v32z * b3) * inv;
- hit = true;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v41x = sup.x;
- var v41y = sup.y;
- var v41z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v42x = sup.x;
- var v42y = sup.y;
- var v42z = sup.z;
- var v4x = v42x - v41x;
- var v4y = v42y - v41y;
- var v4z = v42z - v41z;
- var separation = -(v4x * nx + v4y * ny + v4z * nz);
- if ((v4x - v3x) * nx + (v4y - v3y) * ny + (v4z - v3z) * nz <= 0.01 || separation >= 0) {
- if (hit) {
- sep.init(-nx, -ny, -nz);
- pos.init((p1x + p2x) * 0.5, (p1y + p2y) * 0.5, (p1z + p2z) * 0.5);
- dep.x = separation;
- return true;
- }
- return false;
- }
- if (
- (v4y * v1z - v4z * v1y) * v0x +
- (v4z * v1x - v4x * v1z) * v0y +
- (v4x * v1y - v4y * v1x) * v0z < 0
- ) {
- if (
- (v4y * v2z - v4z * v2y) * v0x +
- (v4z * v2x - v4x * v2z) * v0y +
- (v4x * v2y - v4y * v2x) * v0z < 0
- ) {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- } else {
- v3x = v4x;
- v3y = v4y;
- v3z = v4z;
- v31x = v41x;
- v31y = v41y;
- v31z = v41z;
- v32x = v42x;
- v32y = v42y;
- v32z = v42z;
- }
- } else {
- if (
- (v4y * v3z - v4z * v3y) * v0x +
- (v4z * v3x - v4x * v3z) * v0y +
- (v4x * v3y - v4y * v3x) * v0z < 0
- ) {
- v2x = v4x;
- v2y = v4y;
- v2z = v4z;
- v21x = v41x;
- v21y = v41y;
- v21z = v41z;
- v22x = v42x;
- v22y = v42y;
- v22z = v42z;
- } else {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- }
- }
- }
- }
- //return false;
- };
- OIMO.CylinderCylinderCollisionDetector.prototype.supportPoint = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var radx = ldx;
- var radz = ldz;
- var len = radx * radx + radz * radz;
- var rad = c.radius;
- var hh = c.halfHeight;
- var ox;
- var oy;
- var oz;
- if (len == 0) {
- if (ldy < 0) {
- ox = rad;
- oy = -hh;
- oz = 0;
- } else {
- ox = rad;
- oy = hh;
- oz = 0;
- }
- } else {
- len = c.radius / OIMO.sqrt(len);
- if (ldy < 0) {
- ox = radx * len;
- oy = -hh;
- oz = radz * len;
- } else {
- ox = radx * len;
- oy = hh;
- oz = radz * len;
- }
- }
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.CylinderCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var c1;
- var c2;
- if (shape1.id < shape2.id) {
- c1 = shape1;
- c2 = shape2;
- } else {
- c1 = shape2;
- c2 = shape1;
- }
- var p1 = c1.position;
- var p2 = c2.position;
- var p1x = p1.x;
- var p1y = p1.y;
- var p1z = p1.z;
- var p2x = p2.x;
- var p2y = p2.y;
- var p2z = p2.z;
- var h1 = c1.halfHeight;
- var h2 = c2.halfHeight;
- var n1 = c1.normalDirection;
- var n2 = c2.normalDirection;
- var d1 = c1.halfDirection;
- var d2 = c2.halfDirection;
- var r1 = c1.radius;
- var r2 = c2.radius;
- var n1x = n1.x;
- var n1y = n1.y;
- var n1z = n1.z;
- var n2x = n2.x;
- var n2y = n2.y;
- var n2z = n2.z;
- var d1x = d1.x;
- var d1y = d1.y;
- var d1z = d1.z;
- var d2x = d2.x;
- var d2y = d2.y;
- var d2z = d2.z;
- var dx = p1x - p2x;
- var dy = p1y - p2y;
- var dz = p1z - p2z;
- var len;
- var len1;
- var len2;
- var c;
- var c1x;
- var c1y;
- var c1z;
- var c2x;
- var c2y;
- var c2z;
- var tx;
- var ty;
- var tz;
- var sx;
- var sy;
- var sz;
- var ex;
- var ey;
- var ez;
- var depth1;
- var depth2;
- var dot;
- var t1;
- var t2;
- var sep = new OIMO.Vec3();
- var pos = new OIMO.Vec3();
- var dep = new OIMO.Vec3();
- if (!this.getSep(c1, c2, sep, pos, dep)) return;
- var dot1 = sep.x * n1x + sep.y * n1y + sep.z * n1z;
- var dot2 = sep.x * n2x + sep.y * n2y + sep.z * n2z;
- var right1 = dot1 > 0;
- var right2 = dot2 > 0;
- if (!right1) dot1 = -dot1;
- if (!right2) dot2 = -dot2;
- var state = 0;
- if (dot1 > 0.999 || dot2 > 0.999) {
- if (dot1 > dot2) state = 1;
- else state = 2;
- }
- var nx;
- var ny;
- var nz;
- var depth = dep.x;
- var r00;
- var r01;
- var r02;
- var r10;
- var r11;
- var r12;
- var r20;
- var r21;
- var r22;
- var px;
- var py;
- var pz;
- var pd;
- var a;
- var b;
- var e;
- var f;
- nx = sep.x;
- ny = sep.y;
- nz = sep.z;
- switch (state) {
- case 0:
- manifold.addPoint(pos.x, pos.y, pos.z, nx, ny, nz, depth, false);
- break;
- case 1:
- if (right1) {
- c1x = p1x + d1x;
- c1y = p1y + d1y;
- c1z = p1z + d1z;
- nx = n1x;
- ny = n1y;
- nz = n1z;
- } else {
- c1x = p1x - d1x;
- c1y = p1y - d1y;
- c1z = p1z - d1z;
- nx = -n1x;
- ny = -n1y;
- nz = -n1z;
- }
- dot = nx * n2x + ny * n2y + nz * n2z;
- if (dot < 0) len = h2;
- else len = -h2;
- c2x = p2x + len * n2x;
- c2y = p2y + len * n2y;
- c2z = p2z + len * n2z;
- if (dot2 >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * n2x + ty * n2y + tz * n2z;
- dx = len * n2x - tx;
- dy = len * n2y - ty;
- dz = len * n2z - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) break;
- len = r2 / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = c2x + dx;
- ty = c2y + dy;
- tz = c2z + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = n2x * n2x * 1.5 - 0.5;
- r01 = n2x * n2y * 1.5 - n2z * 0.866025403;
- r02 = n2x * n2z * 1.5 + n2y * 0.866025403;
- r10 = n2y * n2x * 1.5 + n2z * 0.866025403;
- r11 = n2y * n2y * 1.5 - 0.5;
- r12 = n2y * n2z * 1.5 - n2x * 0.866025403;
- r20 = n2z * n2x * 1.5 - n2y * 0.866025403;
- r21 = n2z * n2y * 1.5 + n2x * 0.866025403;
- r22 = n2z * n2z * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c2x;
- py = (dy = py) + c2y;
- pz = (dz = pz) + c2z;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- if (pd <= 0) {
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c2x;
- py = (dy = py) + c2y;
- pz = (dz = pz) + c2z;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- if (pd <= 0) {
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- depth1 = nx * (sx - c1x) + ny * (sy - c1y) + nz * (sz - c1z);
- sx -= depth1 * nx;
- sy -= depth1 * ny;
- sz -= depth1 * nz;
- if (dot > 0) {
- ex = tx + n2x * h2 * 2;
- ey = ty + n2y * h2 * 2;
- ez = tz + n2z * h2 * 2;
- } else {
- ex = tx - n2x * h2 * 2;
- ey = ty - n2y * h2 * 2;
- ez = tz - n2z * h2 * 2;
- }
- depth2 = nx * (ex - c1x) + ny * (ey - c1y) + nz * (ez - c1z);
- ex -= depth2 * nx;
- ey -= depth2 * ny;
- ez -= depth2 * nz;
- dx = c1x - sx;
- dy = c1y - sy;
- dz = c1z - sz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- a = dx * dx + dy * dy + dz * dz;
- b = dx * tx + dy * ty + dz * tz;
- e = tx * tx + ty * ty + tz * tz;
- f = b * b - e * (a - r1 * r1);
- if (f < 0) break;
- f = OIMO.sqrt(f);
- t1 = (b + f) / e;
- t2 = (b - f) / e;
- if (t2 < t1) {
- len = t1;
- t1 = t2;
- t2 = len;
- }
- if (t2 > 1) t2 = 1;
- if (t1 < 0) t1 = 0;
- tx = sx + (ex - sx) * t1;
- ty = sy + (ey - sy) * t1;
- tz = sz + (ez - sz) * t1;
- ex = sx + (ex - sx) * t2;
- ey = sy + (ey - sy) * t2;
- ez = sz + (ez - sz) * t2;
- sx = tx;
- sy = ty;
- sz = tz;
- len = depth1 + (depth2 - depth1) * t1;
- depth2 = depth1 + (depth2 - depth1) * t2;
- depth1 = len;
- if (depth1 < 0) manifold.addPoint(sx, sy, sz, nx, ny, nz, pd, false);
- if (depth2 < 0) manifold.addPoint(ex, ey, ez, nx, ny, nz, pd, false);
- }
- break;
- case 2:
- if (right2) {
- c2x = p2x - d2x;
- c2y = p2y - d2y;
- c2z = p2z - d2z;
- nx = -n2x;
- ny = -n2y;
- nz = -n2z;
- } else {
- c2x = p2x + d2x;
- c2y = p2y + d2y;
- c2z = p2z + d2z;
- nx = n2x;
- ny = n2y;
- nz = n2z;
- }
- dot = nx * n1x + ny * n1y + nz * n1z;
- if (dot < 0) len = h1;
- else len = -h1;
- c1x = p1x + len * n1x;
- c1y = p1y + len * n1y;
- c1z = p1z + len * n1z;
- if (dot1 >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * n1x + ty * n1y + tz * n1z;
- dx = len * n1x - tx;
- dy = len * n1y - ty;
- dz = len * n1z - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) break;
- len = r1 / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = c1x + dx;
- ty = c1y + dy;
- tz = c1z + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = n1x * n1x * 1.5 - 0.5;
- r01 = n1x * n1y * 1.5 - n1z * 0.866025403;
- r02 = n1x * n1z * 1.5 + n1y * 0.866025403;
- r10 = n1y * n1x * 1.5 + n1z * 0.866025403;
- r11 = n1y * n1y * 1.5 - 0.5;
- r12 = n1y * n1z * 1.5 - n1x * 0.866025403;
- r20 = n1z * n1x * 1.5 - n1y * 0.866025403;
- r21 = n1z * n1y * 1.5 + n1x * 0.866025403;
- r22 = n1z * n1z * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c1x;
- py = (dy = py) + c1y;
- pz = (dz = pz) + c1z;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- if (pd <= 0) {
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c1x;
- py = (dy = py) + c1y;
- pz = (dz = pz) + c1z;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- if (pd <= 0) {
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- depth1 = nx * (sx - c2x) + ny * (sy - c2y) + nz * (sz - c2z);
- sx -= depth1 * nx;
- sy -= depth1 * ny;
- sz -= depth1 * nz;
- if (dot > 0) {
- ex = tx + n1x * h1 * 2;
- ey = ty + n1y * h1 * 2;
- ez = tz + n1z * h1 * 2;
- } else {
- ex = tx - n1x * h1 * 2;
- ey = ty - n1y * h1 * 2;
- ez = tz - n1z * h1 * 2;
- }
- depth2 = nx * (ex - c2x) + ny * (ey - c2y) + nz * (ez - c2z);
- ex -= depth2 * nx;
- ey -= depth2 * ny;
- ez -= depth2 * nz;
- dx = c2x - sx;
- dy = c2y - sy;
- dz = c2z - sz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- a = dx * dx + dy * dy + dz * dz;
- b = dx * tx + dy * ty + dz * tz;
- e = tx * tx + ty * ty + tz * tz;
- f = b * b - e * (a - r2 * r2);
- if (f < 0) break;
- f = OIMO.sqrt(f);
- t1 = (b + f) / e;
- t2 = (b - f) / e;
- if (t2 < t1) {
- len = t1;
- t1 = t2;
- t2 = len;
- }
- if (t2 > 1) t2 = 1;
- if (t1 < 0) t1 = 0;
- tx = sx + (ex - sx) * t1;
- ty = sy + (ey - sy) * t1;
- tz = sz + (ez - sz) * t1;
- ex = sx + (ex - sx) * t2;
- ey = sy + (ey - sy) * t2;
- ez = sz + (ez - sz) * t2;
- sx = tx;
- sy = ty;
- sz = tz;
- len = depth1 + (depth2 - depth1) * t1;
- depth2 = depth1 + (depth2 - depth1) * t2;
- depth1 = len;
- if (depth1 < 0) {
- manifold.addPoint(sx, sy, sz, -nx, -ny, -nz, depth1, false);
- }
- if (depth2 < 0) {
- manifold.addPoint(ex, ey, ez, -nx, -ny, -nz, depth2, false);
- }
- }
- break;
- }
- };
- OIMO.SphereCylinderCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.SphereCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereCylinderCollisionDetector.prototype.constructor = OIMO.SphereCylinderCollisionDetector;
- OIMO.SphereCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s;
- var c;
- if (this.flip) {
- s = shape2;
- c = shape1;
- } else {
- s = shape1;
- c = shape2;
- }
- var ps = s.position;
- var psx = ps.x;
- var psy = ps.y;
- var psz = ps.z;
- var pc = c.position;
- var pcx = pc.x;
- var pcy = pc.y;
- var pcz = pc.z;
- var dirx = c.normalDirection.x;
- var diry = c.normalDirection.y;
- var dirz = c.normalDirection.z;
- var rads = s.radius;
- var radc = c.radius;
- var rad2 = rads + radc;
- var halfh = c.halfHeight;
- var dx = psx - pcx;
- var dy = psy - pcy;
- var dz = psz - pcz;
- var dot = dx * dirx + dy * diry + dz * dirz;
- if (dot < -halfh - rads || dot > halfh + rads) return;
- var cx = pcx + dot * dirx;
- var cy = pcy + dot * diry;
- var cz = pcz + dot * dirz;
- var d2x = psx - cx;
- var d2y = psy - cy;
- var d2z = psz - cz;
- var len = d2x * d2x + d2y * d2y + d2z * d2z;
- if (len > rad2 * rad2) return;
- if (len > radc * radc) {
- len = radc / OIMO.sqrt(len);
- d2x *= len;
- d2y *= len;
- d2z *= len;
- }
- if (dot < -halfh) dot = -halfh;
- else if (dot > halfh) dot = halfh;
- cx = pcx + dot * dirx + d2x;
- cy = pcy + dot * diry + d2y;
- cz = pcz + dot * dirz + d2z;
- dx = cx - psx;
- dy = cy - psy;
- dz = cz - psz;
- len = dx * dx + dy * dy + dz * dz;
- var invLen;
- if (len > 0 && len < rads * rads) {
- len = OIMO.sqrt(len);
- invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- ///result.addContactInfo(psx+dx*rads,psy+dy*rads,psz+dz*rads,dx,dy,dz,len-rads,s,c,0,0,false);
- manifold.addPoint(psx + dx * rads, psy + dy * rads, psz + dz * rads, dx, dy, dz, len - rads, this.flip);
- }
- };
- /**
- * Class for checking collisions between 2 tetras,
- * a shape that is made with 4 vertices and 4 faces
- * arranged in triangles. With this algorigthm, soft
- * body physics are possible and easier to implement.
- * @author xprogram
- */
- OIMO.TetraTetraCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.TetraTetraCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.TetraTetraCollisionDetector.prototype.constructor = OIMO.TetraTetraCollisionDetector;
- OIMO.TetraTetraCollisionDetector.prototype.detectCollision = function (tet1, tet2, manifold) {
- /*
- * What we are doing:
- * Each tetra is represented by four 3D triangles. The only
- * quick way of finding if another tetra is within the other
- * tetra is to see if a single vertex is within the triangles
- * of the other tetra. So, for example, a tetra is represented
- * by points B, C, D and E with triangles BCD, BCE, DCE and BDE.
- * There is another tetra with a vertex A which was detected for
- * collision by the broadphase. Now, if the point A is between ALL
- * triangles of the other tetra (BCD, BCE, etc.) then the collision
- * is valid and we can pass point A to the manifold. Since the only
- * points on the tetra are the 4 vertices, collision detection is
- * not so complex. However, it can be time-consuming because we
- * need to split the 3D triangles into three 2D triangles each for
- * collision detection.
- */
- var i, j, vec, fs1 = tet1.faces, vs1 = tet1.verts, fs2 = tet2.faces, vs2 = tet2.verts;
- var j1, j2, j3, ts = 0; // Triangle vertices `j1`, `j2` and `j3`
- // fs is undeclared
- var fs = fs1;
- for (i = 0; i < 4; i++) {
- vec = vs1[i];
- for (j = 0; j < 4; j++) {
- j1 = vs2[fs[i].a];
- j2 = vs2[fs[i].b];
- j3 = vs2[fs[i].c];
- if (
- tricheck(pt(vec.x, vec.y), pt(j1.x, j1.y), pt(j2.x, j2.y), pt(j3.x, j3.y)) &&
- tricheck(pt(vec.x, vec.z), pt(j1.x, j1.z), pt(j2.x, j2.z), pt(j3.x, j3.z)) &&
- tricheck(pt(vec.z, vec.y), pt(j1.z, j1.y), pt(j2.z, j2.y), pt(j3.z, j3.y))
- )
- ts++;
- if (ts === 4) // Only add point if it is inside all 4 triangles
- manifold.addPoint(vec);
- }
- }
- };
- // Taken from: http://jsfiddle.net/PerroAZUL/zdaY8/1/
- function tricheck(p, p0, p1, p2) {
- var A = 0.5 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
- var sg = A < 0 ? -1 : 1;
- var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sg;
- var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sg;
- return s > 0 && t > 0 && (s + t) < 2 * A * sg;
- }
- function pt(x, y) { return { x: x, y: y }; }
- /**
- * An axis-aligned bounding box.
- * @author saharan
- * @author lo-th
- */
- OIMO.AABB = function (minX, maxX, minY, maxY, minZ, maxZ) {
- this.elements = new OIMO_ARRAY_TYPE(6);
- var te = this.elements;
- te[0] = minX || 0; te[1] = minY || 0; te[2] = minZ || 0;
- te[3] = maxX || 0; te[4] = maxY || 0; te[5] = maxZ || 0;
- };
- OIMO.AABB.prototype = {
- constructor: OIMO.AABB,
- set: function (minX, maxX, minY, maxY, minZ, maxZ) {
- var te = this.elements;
- te[0] = minX; te[3] = maxX;
- te[1] = minY; te[4] = maxY;
- te[2] = minZ; te[5] = maxZ;
- return this;
- },
- intersectTest: function (aabb) {
- var te = this.elements;
- var ue = aabb.elements;
- return te[0] > ue[3] || te[1] > ue[4] || te[2] > ue[5] || te[3] < ue[0] || te[4] < ue[1] || te[5] < ue[2];
- },
- intersectTestTwo: function (aabb) {
- var te = this.elements;
- var ue = aabb.elements;
- return te[0] < ue[0] || te[1] < ue[1] || te[2] < ue[2] || te[3] > ue[3] || te[4] > ue[4] || te[5] > ue[5];
- },
- clone: function () {
- return new this.constructor().fromArray(this.elements);
- },
- copy: function (aabb, margin) {
- var m = margin || 0;
- var me = aabb.elements;
- this.set(me[0] - m, me[3] + m, me[1] - m, me[4] + m, me[2] - m, me[5] + m);
- return this;
- },
- fromArray: function (array) {
- this.elements.set(array);
- return this;
- },
- // Set this AABB to the combined AABB of aabb1 and aabb2.
- combine: function (aabb1, aabb2) {
- var a = aabb1.elements;
- var b = aabb2.elements;
- var te = this.elements;
- te[0] = a[0] < b[0] ? a[0] : b[0];
- te[1] = a[1] < b[1] ? a[1] : b[1];
- te[2] = a[2] < b[2] ? a[2] : b[2];
- te[3] = a[3] > b[3] ? a[3] : b[3];
- te[4] = a[4] > b[4] ? a[4] : b[4];
- te[5] = a[5] > b[5] ? a[5] : b[5];
- return this;
- },
- // Get the surface area.
- surfaceArea: function () {
- var te = this.elements;
- var a = te[3] - te[0];
- var h = te[4] - te[1];
- var d = te[5] - te[2];
- return 2 * (a * (h + d) + h * d);
- },
- // Get whether the AABB intersects with the point or not.
- intersectsWithPoint: function (x, y, z) {
- var te = this.elements;
- return x >= te[0] && x <= te[3] && y >= te[1] && y <= te[4] && z >= te[2] && z <= te[5];
- },
- /**
- * Set the AABB from an array
- * of vertices. From THREE.
- * @author mrdoob
- * @author xprogram
- */
- setFromPoints: function (arr) {
- this.makeEmpty();
- for (var i = 0; i < arr.length; i++) {
- this.expandByPoint(arr[i]);
- }
- },
- makeEmpty: function () {
- this.set(-Infinity, -Infinity, -Infinity, Infinity, Infinity, Infinity);
- },
- expandByPoint: function (pt) {
- var te = this.elements;
- this.set(
- OIMO.min(te[0], pt.x), OIMO.min(te[1], pt.y), OIMO.min(te[2], pt.z),
- OIMO.max(te[3], pt.x), OIMO.max(te[4], pt.y), OIMO.max(te[5], pt.z)
- );
- }
- };
- /**
- * A proxy is used for broad-phase collecting pairs that can be colliding.
- */
- OIMO.Proxy = function (shape) {
- // The parent shape.
- this.shape = shape;
- // The axis-aligned bounding box.
- this.aabb = shape.aabb;
- };
- OIMO.Proxy.prototype = {
- constructor: OIMO.Proxy,
- // Update the proxy.
- update: function () {
- OIMO.Error("Proxy", "Inheritance error.");
- }
- };
- /**
- * A basic implementation of proxies.
- * @author saharan
- */
- OIMO.BasicProxy = function (shape) {
- OIMO.Proxy.call(this, shape);
- this.id = OIMO.proxyID++;
- };
- OIMO.BasicProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.BasicProxy.prototype.constructor = OIMO.BasicProxy;
- OIMO.BasicProxy.prototype.update = function () {
- };
- /**
- * The broad-phase is used for collecting all possible pairs for collision.
- */
- OIMO.BroadPhase = function () {
- this.types = OIMO.BR_NULL;
- this.numPairChecks = 0;
- this.numPairs = 0;
- this.pairs = [];
- };
- OIMO.BroadPhase.prototype = {
- constructor: OIMO.BroadPhase,
- /**
- * Create a new proxy.
- * @param shape
- * @return
- */
- createProxy: function (shape) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Add the proxy into the broad-phase.
- * @param proxy
- */
- addProxy: function (proxy) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Remove the proxy from the broad-phase.
- * @param proxy
- */
- removeProxy: function (proxy) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Returns whether the pair is available or not.
- * @param s1
- * @param s2
- * @return
- */
- isAvailablePair: function (s1, s2) {
- var b1 = s1.parent;
- var b2 = s2.parent;
- if (b1 == b2 || // same parents
- (!b1.isDynamic && !b2.isDynamic) || // static or kinematic object
- (s1.belongsTo & s2.collidesWith) == 0 ||
- (s2.belongsTo & s1.collidesWith) == 0 // collision filtering
- ) { return false; }
- var js;
- if (b1.numJoints < b2.numJoints) js = b1.jointLink;
- else js = b2.jointLink;
- while (js !== null) {
- var joint = js.joint;
- if (!joint.allowCollision && ((joint.body1 == b1 && joint.body2 == b2) || (joint.body1 == b2 && joint.body2 == b1))) { return false; }
- js = js.next;
- }
- return true;
- },
- // Detect overlapping pairs.
- detectPairs: function () {
- // clear old
- this.pairs = [];
- this.numPairs = 0;
- this.numPairChecks = 0;
- this.collectPairs();
- },
- collectPairs: function () {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- addPair: function (s1, s2) {
- var pair = new OIMO.Pair(s1, s2);
- this.pairs.push(pair);
- this.numPairs++;
- }
- };
- /**
- * A broad-phase algorithm with brute-force search.
- * This always checks for all possible pairs.
- */
- OIMO.BruteForceBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_BRUTE_FORCE;;
- //this.numProxies=0;
- ///this.maxProxies = 256;
- this.proxies = [];
- //this.proxies.length = 256;
- };
- OIMO.BruteForceBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.BruteForceBroadPhase.prototype.constructor = OIMO.BruteForceBroadPhase;
- OIMO.BruteForceBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.BasicProxy(shape);
- };
- OIMO.BruteForceBroadPhase.prototype.addProxy = function (proxy) {
- /*if(this.numProxies==this.maxProxies){
- //this.maxProxies<<=1;
- this.maxProxies*=2;
- var newProxies=[];
- newProxies.length = this.maxProxies;
- var i = this.numProxies;
- while(i--){
- //for(var i=0, l=this.numProxies;i<l;i++){
- newProxies[i]=this.proxies[i];
- }
- this.proxies=newProxies;
- }*/
- //this.proxies[this.numProxies++] = proxy;
- this.proxies.push(proxy);
- //this.numProxies++;
- };
- OIMO.BruteForceBroadPhase.prototype.removeProxy = function (proxy) {
- var n = this.proxies.indexOf(proxy);
- if (n > -1) {
- this.proxies.splice(n, 1);
- //this.numProxies--;
- }
- /*var i = this.numProxies;
- while(i--){
- //for(var i=0, l=this.numProxies;i<l;i++){
- if(this.proxies[i] == proxy){
- this.proxies[i] = this.proxies[--this.numProxies];
- this.proxies[this.numProxies] = null;
- return;
- }
- }*/
- };
- OIMO.BruteForceBroadPhase.prototype.collectPairs = function () {
- var i = 0, j, p1, p2;
- var px = this.proxies;
- var l = px.length;//this.numProxies;
- //var ar1 = [];
- //var ar2 = [];
- //for( i = px.length ; i-- ; ar1[ i ] = px[ i ] ){};
- //for( i = px.length ; i-- ; ar2[ i ] = px[ i ] ){};
- //var ar1 = JSON.parse(JSON.stringify(this.proxies))
- //var ar2 = JSON.parse(JSON.stringify(this.proxies))
- this.numPairChecks = l * (l - 1) >> 1;
- //this.numPairChecks=this.numProxies*(this.numProxies-1)*0.5;
- while (i < l) {
- p1 = px[i++];
- j = i + 1;
- while (j < l) {
- p2 = px[j++];
- if (p1.aabb.intersectTest(p2.aabb) || !this.isAvailablePair(p1.shape, p2.shape)) continue;
- this.addPair(p1.shape, p2.shape);
- }
- }
- };
- /**
- * A pair of shapes that may collide.
- * @author saharan
- */
- OIMO.Pair = function (s1, s2) {
- // The first shape.
- this.shape1 = s1 || null;
- // The second shape.
- this.shape2 = s2 || null;
- };
- /**
- * A projection axis for sweep and prune broad-phase.
- * @author saharan
- */
- OIMO.SAPAxis = function () {
- this.numElements = 0;
- this.bufferSize = 256;
- this.elements = [];
- this.elements.length = this.bufferSize;
- this.stack = new OIMO_ARRAY_TYPE(64);
- };
- OIMO.SAPAxis.prototype = {
- constructor: OIMO.SAPAxis,
- addElements: function (min, max) {
- if (this.numElements + 2 >= this.bufferSize) {
- //this.bufferSize<<=1;
- this.bufferSize *= 2;
- var newElements = [];
- var i = this.numElements;
- while (i--) {
- //for(var i=0, l=this.numElements; i<l; i++){
- newElements[i] = this.elements[i];
- }
- }
- this.elements[this.numElements++] = min;
- this.elements[this.numElements++] = max;
- },
- removeElements: function (min, max) {
- var minIndex = -1;
- var maxIndex = -1;
- for (var i = 0, l = this.numElements; i < l; i++) {
- var e = this.elements[i];
- if (e == min || e == max) {
- if (minIndex == -1) {
- minIndex = i;
- } else {
- maxIndex = i;
- break;
- }
- }
- }
- for (i = minIndex + 1, l = maxIndex; i < l; i++) {
- this.elements[i - 1] = this.elements[i];
- }
- for (i = maxIndex + 1, l = this.numElements; i < l; i++) {
- this.elements[i - 2] = this.elements[i];
- }
- this.elements[--this.numElements] = null;
- this.elements[--this.numElements] = null;
- },
- sort: function () {
- var count = 0;
- var threshold = 1;
- while ((this.numElements >> threshold) != 0) threshold++;
- threshold = threshold * this.numElements >> 2;
- count = 0;
- var giveup = false;
- var elements = this.elements;
- for (var i = 1, l = this.numElements; i < l; i++) { // try insertion sort
- var tmp = elements[i];
- var pivot = tmp.value;
- var tmp2 = elements[i - 1];
- if (tmp2.value > pivot) {
- var j = i;
- do {
- elements[j] = tmp2;
- if (--j == 0) break;
- tmp2 = elements[j - 1];
- } while (tmp2.value > pivot);
- elements[j] = tmp;
- count += i - j;
- if (count > threshold) {
- giveup = true; // stop and use quick sort
- break;
- }
- }
- }
- if (!giveup) return;
- count = 2; var stack = this.stack;
- stack[0] = 0;
- stack[1] = this.numElements - 1;
- while (count > 0) {
- var right = stack[--count];
- var left = stack[--count];
- var diff = right - left;
- if (diff > 16) { // quick sort
- //var mid=left+(diff>>1);
- var mid = left + (OIMO.floor(diff * 0.5));
- tmp = elements[mid];
- elements[mid] = elements[right];
- elements[right] = tmp;
- pivot = tmp.value;
- i = left - 1;
- j = right;
- while (true) {
- var ei;
- var ej;
- do { ei = elements[++i]; } while (ei.value < pivot);
- do { ej = elements[--j]; } while (pivot < ej.value && j != left);
- if (i >= j) break;
- elements[i] = ej;
- elements[j] = ei;
- }
- elements[right] = elements[i];
- elements[i] = tmp;
- if (i - left > right - i) {
- stack[count++] = left;
- stack[count++] = i - 1;
- stack[count++] = i + 1;
- stack[count++] = right;
- } else {
- stack[count++] = i + 1;
- stack[count++] = right;
- stack[count++] = left;
- stack[count++] = i - 1;
- }
- } else {
- for (i = left + 1; i <= right; i++) {
- tmp = elements[i];
- pivot = tmp.value;
- tmp2 = elements[i - 1];
- if (tmp2.value > pivot) {
- j = i;
- do {
- elements[j] = tmp2;
- if (--j == 0) break;
- tmp2 = elements[j - 1];
- } while (tmp2.value > pivot);
- elements[j] = tmp;
- }
- }
- }
- }
- },
- calculateTestCount: function () {
- var num = 1;
- var sum = 0;
- for (var i = 1, l = this.numElements; i < l; i++) {
- if (this.elements[i].max) {
- num--;
- } else {
- sum += num;
- num++;
- }
- }
- return sum;
- }
- }
- /**
- * A broad-phase collision detection algorithm using sweep and prune.
- * @author saharan
- * @author lo-th
- */
- OIMO.SAPBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_SWEEP_AND_PRUNE;
- this.numElementsD = 0;
- this.numElementsS = 0;
- // dynamic proxies
- this.axesD = [
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis()
- ];
- // static or sleeping proxies
- this.axesS = [
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis()
- ];
- this.index1 = 0;
- this.index2 = 1;
- };
- OIMO.SAPBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.SAPBroadPhase.prototype.constructor = OIMO.SAPBroadPhase;
- OIMO.SAPBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.SAPProxy(this, shape);
- };
- OIMO.SAPBroadPhase.prototype.addProxy = function (proxy) {
- var p = proxy;
- if (p.isDynamic()) {
- this.axesD[0].addElements(p.min[0], p.max[0]);
- this.axesD[1].addElements(p.min[1], p.max[1]);
- this.axesD[2].addElements(p.min[2], p.max[2]);
- p.belongsTo = 1;
- this.numElementsD += 2;
- } else {
- this.axesS[0].addElements(p.min[0], p.max[0]);
- this.axesS[1].addElements(p.min[1], p.max[1]);
- this.axesS[2].addElements(p.min[2], p.max[2]);
- p.belongsTo = 2;
- this.numElementsS += 2;
- }
- };
- OIMO.SAPBroadPhase.prototype.removeProxy = function (proxy) {
- var p = proxy;
- if (p.belongsTo == 0) return;
- /*else if ( p.belongsTo == 1 ) {
- this.axesD[0].removeElements( p.min[0], p.max[0] );
- this.axesD[1].removeElements( p.min[1], p.max[1] );
- this.axesD[2].removeElements( p.min[2], p.max[2] );
- this.numElementsD -= 2;
- } else if ( p.belongsTo == 2 ) {
- this.axesS[0].removeElements( p.min[0], p.max[0] );
- this.axesS[1].removeElements( p.min[1], p.max[1] );
- this.axesS[2].removeElements( p.min[2], p.max[2] );
- this.numElementsS -= 2;
- }*/
- switch (p.belongsTo) {
- case 1:
- this.axesD[0].removeElements(p.min[0], p.max[0]);
- this.axesD[1].removeElements(p.min[1], p.max[1]);
- this.axesD[2].removeElements(p.min[2], p.max[2]);
- this.numElementsD -= 2;
- break;
- case 2:
- this.axesS[0].removeElements(p.min[0], p.max[0]);
- this.axesS[1].removeElements(p.min[1], p.max[1]);
- this.axesS[2].removeElements(p.min[2], p.max[2]);
- this.numElementsS -= 2;
- break;
- }
- p.belongsTo = 0;
- };
- OIMO.SAPBroadPhase.prototype.collectPairs = function () {
- if (this.numElementsD == 0) return;
- var axis1 = this.axesD[this.index1];
- var axis2 = this.axesD[this.index2];
- axis1.sort();
- axis2.sort();
- var count1 = axis1.calculateTestCount();
- var count2 = axis2.calculateTestCount();
- var elementsD;
- var elementsS;
- if (count1 <= count2) {// select the best axis
- axis2 = this.axesS[this.index1];
- axis2.sort();
- elementsD = axis1.elements;
- elementsS = axis2.elements;
- } else {
- axis1 = this.axesS[this.index2];
- axis1.sort();
- elementsD = axis2.elements;
- elementsS = axis1.elements;
- this.index1 ^= this.index2;
- this.index2 ^= this.index1;
- this.index1 ^= this.index2;
- }
- var activeD;
- var activeS;
- var p = 0;
- var q = 0;
- while (p < this.numElementsD) {
- var e1;
- var dyn;
- if (q == this.numElementsS) {
- e1 = elementsD[p];
- dyn = true;
- p++;
- } else {
- var d = elementsD[p];
- var s = elementsS[q];
- if (d.value < s.value) {
- e1 = d;
- dyn = true;
- p++;
- } else {
- e1 = s;
- dyn = false;
- q++;
- }
- }
- if (!e1.max) {
- var s1 = e1.proxy.shape;
- var min1 = e1.min1.value;
- var max1 = e1.max1.value;
- var min2 = e1.min2.value;
- var max2 = e1.max2.value;
- for (var e2 = activeD; e2 != null; e2 = e2.pair) {// test for dynamic
- var s2 = e2.proxy.shape;
- this.numPairChecks++;
- if (min1 > e2.max1.value || max1 < e2.min1.value || min2 > e2.max2.value || max2 < e2.min2.value || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- }
- if (dyn) {
- for (e2 = activeS; e2 != null; e2 = e2.pair) {// test for static
- s2 = e2.proxy.shape;
- this.numPairChecks++;
- if (min1 > e2.max1.value || max1 < e2.min1.value || min2 > e2.max2.value || max2 < e2.min2.value || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- }
- e1.pair = activeD;
- activeD = e1;
- } else {
- e1.pair = activeS;
- activeS = e1;
- }
- } else {
- var min = e1.pair;
- if (dyn) {
- if (min == activeD) {
- activeD = activeD.pair;
- continue;
- } else {
- e1 = activeD;
- }
- } else {
- if (min == activeS) {
- activeS = activeS.pair;
- continue;
- } else {
- e1 = activeS;
- }
- }
- do {
- e2 = e1.pair;
- if (e2 == min) {
- e1.pair = e2.pair;
- break;
- }
- e1 = e2;
- } while (e1 != null);
- }
- }
- this.index2 = (this.index1 | this.index2) ^ 3;
- };
- /**
- * An element of proxies.
- * @author saharan
- */
- OIMO.SAPElement = function (proxy, max) {
- // The parent proxy
- this.proxy = proxy;
- // The pair element.
- this.pair = null;
- // The minimum element on other axis.
- this.min1 = null;
- // The maximum element on other axis.
- this.max1 = null;
- // The minimum element on other axis.
- this.min2 = null;
- // The maximum element on other axis.
- this.max2 = null;
- // Whether the element has maximum value or not.
- this.max = max;
- // The value of the element.
- this.value = 0;
- };
- /**
- * A proxy for sweep and prune broad-phase.
- * @author saharan
- * @author lo-th
- */
- OIMO.SAPProxy = function (sap, shape) {
- OIMO.Proxy.call(this, shape);
- // Type of the axis to which the proxy belongs to. [0:none, 1:dynamic, 2:static]
- this.belongsTo = 0;
- // The maximum elements on each axis.
- this.max = [];
- // The minimum elements on each axis.
- this.min = [];
- this.sap = sap;
- this.min[0] = new OIMO.SAPElement(this, false);
- this.max[0] = new OIMO.SAPElement(this, true);
- this.min[1] = new OIMO.SAPElement(this, false);
- this.max[1] = new OIMO.SAPElement(this, true);
- this.min[2] = new OIMO.SAPElement(this, false);
- this.max[2] = new OIMO.SAPElement(this, true);
- this.max[0].pair = this.min[0];
- this.max[1].pair = this.min[1];
- this.max[2].pair = this.min[2];
- this.min[0].min1 = this.min[1];
- this.min[0].max1 = this.max[1];
- this.min[0].min2 = this.min[2];
- this.min[0].max2 = this.max[2];
- this.min[1].min1 = this.min[0];
- this.min[1].max1 = this.max[0];
- this.min[1].min2 = this.min[2];
- this.min[1].max2 = this.max[2];
- this.min[2].min1 = this.min[0];
- this.min[2].max1 = this.max[0];
- this.min[2].min2 = this.min[1];
- this.min[2].max2 = this.max[1];
- };
- OIMO.SAPProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.SAPProxy.prototype.constructor = OIMO.SAPProxy;
- // Returns whether the proxy is dynamic or not.
- OIMO.SAPProxy.prototype.isDynamic = function () {
- var body = this.shape.parent;
- return body.isDynamic && !body.sleeping;
- };
- OIMO.SAPProxy.prototype.update = function () {
- var te = this.aabb.elements;
- this.min[0].value = te[0];
- this.min[1].value = te[1];
- this.min[2].value = te[2];
- this.max[0].value = te[3];
- this.max[1].value = te[4];
- this.max[2].value = te[5];
- if (this.belongsTo == 1 && !this.isDynamic() || this.belongsTo == 2 && this.isDynamic()) {
- this.sap.removeProxy(this);
- this.sap.addProxy(this);
- }
- };
- /**
- * A dynamic bounding volume tree for the broad-phase algorithm.
- * @author saharan
- * @author lo-th
- */
- OIMO.DBVT = function () {
- // The root of the tree.
- this.root = null;
- this.freeNodes = [];
- this.freeNodes.length = 16384;
- this.numFreeNodes = 0;
- this.aabb = new OIMO.AABB();
- };
- OIMO.DBVT.prototype = {
- constructor: OIMO.DBVT,
- /**
- * Move a leaf.
- * @param leaf
- */
- moveLeaf: function (leaf) {
- this.deleteLeaf(leaf);
- this.insertLeaf(leaf);
- },
- /**
- * Insert a leaf to the tree.
- * @param node
- */
- insertLeaf: function (leaf) {
- if (this.root == null) {
- this.root = leaf;
- return;
- }
- var lb = leaf.aabb;
- var sibling = this.root;
- var oldArea;
- var newArea;
- while (sibling.proxy == null) { // descend the node to search the best pair
- var c1 = sibling.child1;
- var c2 = sibling.child2;
- var b = sibling.aabb;
- var c1b = c1.aabb;
- var c2b = c2.aabb;
- oldArea = b.surfaceArea();
- this.aabb.combine(lb, b);
- newArea = this.aabb.surfaceArea();
- var creatingCost = newArea * 2;
- var incrementalCost = (newArea - oldArea) * 2; // cost of creating a new pair with the node
- var discendingCost1 = incrementalCost;
- this.aabb.combine(lb, c1b);
- if (c1.proxy != null) {
- // leaf cost = area(combined aabb)
- discendingCost1 += this.aabb.surfaceArea();
- } else {
- // node cost = area(combined aabb) - area(old aabb)
- discendingCost1 += this.aabb.surfaceArea() - c1b.surfaceArea();
- }
- var discendingCost2 = incrementalCost;
- this.aabb.combine(lb, c2b);
- if (c2.proxy != null) {
- // leaf cost = area(combined aabb)
- discendingCost2 += this.aabb.surfaceArea();
- } else {
- // node cost = area(combined aabb) - area(old aabb)
- discendingCost2 += this.aabb.surfaceArea() - c2b.surfaceArea();
- }
- if (discendingCost1 < discendingCost2) {
- if (creatingCost < discendingCost1) {
- break;// stop descending
- } else {
- sibling = c1;// descend into first child
- }
- } else {
- if (creatingCost < discendingCost2) {
- break;// stop descending
- } else {
- sibling = c2;// descend into second child
- }
- }
- }
- var oldParent = sibling.parent;
- var newParent;
- if (this.numFreeNodes > 0) {
- newParent = this.freeNodes[--this.numFreeNodes];
- } else {
- newParent = new OIMO.DBVTNode();
- }
- newParent.parent = oldParent;
- newParent.child1 = leaf;
- newParent.child2 = sibling;
- newParent.aabb.combine(leaf.aabb, sibling.aabb);
- newParent.height = sibling.height + 1;
- sibling.parent = newParent;
- leaf.parent = newParent;
- if (sibling == this.root) {
- // replace root
- this.root = newParent;
- } else {
- // replace child
- if (oldParent.child1 == sibling) {
- oldParent.child1 = newParent;
- } else {
- oldParent.child2 = newParent;
- }
- }
- // update whole tree
- do {
- newParent = this.balance(newParent);
- this.fix(newParent);
- newParent = newParent.parent;
- } while (newParent != null);
- },
- getBalance: function (node) {
- if (node.proxy != null) return 0;
- return node.child1.height - node.child2.height;
- },
- /*print:function(node,indent,text){
- var hasChild=node.proxy==null;
- if(hasChild)text=this.print(node.child1,indent+1,text);
- for(var i=indent*2;i>=0;i--){
- text+=" ";
- }
- text+=(hasChild?this.getBalance(node):"["+node.proxy.aabb.minX+"]")+"\n";
- if(hasChild)text=this.print(node.child2,indent+1,text);
- return text;
- },*/
- /**
- * Delete a leaf from the tree.
- * @param node
- */
- deleteLeaf: function (leaf) {
- if (leaf == this.root) {
- this.root = null;
- return;
- }
- var parent = leaf.parent;
- var sibling;
- if (parent.child1 == leaf) {
- sibling = parent.child2;
- } else {
- sibling = parent.child1;
- }
- if (parent == this.root) {
- this.root = sibling;
- sibling.parent = null;
- return;
- }
- var grandParent = parent.parent;
- sibling.parent = grandParent;
- if (grandParent.child1 == parent) {
- grandParent.child1 = sibling;
- } else {
- grandParent.child2 = sibling;
- }
- if (this.numFreeNodes < 16384) {
- this.freeNodes[this.numFreeNodes++] = parent;
- }
- do {
- grandParent = this.balance(grandParent);
- this.fix(grandParent);
- grandParent = grandParent.parent;
- } while (grandParent != null);
- },
- balance: function (node) {
- var nh = node.height;
- if (nh < 2) {
- return node;
- }
- var p = node.parent;
- var l = node.child1;
- var r = node.child2;
- var lh = l.height;
- var rh = r.height;
- var balance = lh - rh;
- var t;// for bit operation
- // [ N ]
- // / \
- // [ L ] [ R ]
- // / \ / \
- // [L-L] [L-R] [R-L] [R-R]
- // Is the tree balanced?
- if (balance > 1) {
- var ll = l.child1;
- var lr = l.child2;
- var llh = ll.height;
- var lrh = lr.height;
- // Is L-L higher than L-R?
- if (llh > lrh) {
- // set N to L-R
- l.child2 = node;
- node.parent = l;
- // [ L ]
- // / \
- // [L-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [ R ]
- // set L-R
- node.child1 = lr;
- lr.parent = node;
- // [ L ]
- // / \
- // [L-L] [ N ]
- // / \ / \
- // [...] [...] [L-R] [ R ]
- // fix bounds and heights
- node.aabb.combine(lr.aabb, r.aabb);
- t = lrh - rh;
- node.height = lrh - (t & t >> 31) + 1;
- l.aabb.combine(ll.aabb, node.aabb);
- t = llh - nh;
- l.height = llh - (t & t >> 31) + 1;
- } else {
- // set N to L-L
- l.child1 = node;
- node.parent = l;
- // [ L ]
- // / \
- // [ N ] [L-R]
- // / \ / \
- // [ L ] [ R ] [...] [...]
- // set L-L
- node.child1 = ll;
- ll.parent = node;
- // [ L ]
- // / \
- // [ N ] [L-R]
- // / \ / \
- // [L-L] [ R ] [...] [...]
- // fix bounds and heights
- node.aabb.combine(ll.aabb, r.aabb);
- t = llh - rh;
- node.height = llh - (t & t >> 31) + 1;
- l.aabb.combine(node.aabb, lr.aabb);
- t = nh - lrh;
- l.height = nh - (t & t >> 31) + 1;
- }
- // set new parent of L
- if (p != null) {
- if (p.child1 == node) {
- p.child1 = l;
- } else {
- p.child2 = l;
- }
- } else {
- this.root = l;
- }
- l.parent = p;
- return l;
- } else if (balance < -1) {
- var rl = r.child1;
- var rr = r.child2;
- var rlh = rl.height;
- var rrh = rr.height;
- // Is R-L higher than R-R?
- if (rlh > rrh) {
- // set N to R-R
- r.child2 = node;
- node.parent = r;
- // [ R ]
- // / \
- // [R-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [ R ]
- // set R-R
- node.child2 = rr;
- rr.parent = node;
- // [ R ]
- // / \
- // [R-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [R-R]
- // fix bounds and heights
- node.aabb.combine(l.aabb, rr.aabb);
- t = lh - rrh;
- node.height = lh - (t & t >> 31) + 1;
- r.aabb.combine(rl.aabb, node.aabb);
- t = rlh - nh;
- r.height = rlh - (t & t >> 31) + 1;
- } else {
- // set N to R-L
- r.child1 = node;
- node.parent = r;
- // [ R ]
- // / \
- // [ N ] [R-R]
- // / \ / \
- // [ L ] [ R ] [...] [...]
- // set R-L
- node.child2 = rl;
- rl.parent = node;
- // [ R ]
- // / \
- // [ N ] [R-R]
- // / \ / \
- // [ L ] [R-L] [...] [...]
- // fix bounds and heights
- node.aabb.combine(l.aabb, rl.aabb);
- t = lh - rlh;
- node.height = lh - (t & t >> 31) + 1;
- r.aabb.combine(node.aabb, rr.aabb);
- t = nh - rrh;
- r.height = nh - (t & t >> 31) + 1;
- }
- // set new parent of R
- if (p != null) {
- if (p.child1 == node) {
- p.child1 = r;
- } else {
- p.child2 = r;
- }
- } else {
- this.root = r;
- }
- r.parent = p;
- return r;
- }
- return node;
- },
- fix: function (node) {
- var c1 = node.child1;
- var c2 = node.child2;
- node.aabb.combine(c1.aabb, c2.aabb);
- //var h1 = c1.height;
- //var h2 = c2.height;
- node.height = c1.height < c2.height ? c2.height + 1 : c1.height + 1;
- /*if( h1 < h2 ) {
- node.height = h2+1;
- }else{
- node.height = h1+1;
- }*/
- }
- }
- /**
- * A broad-phase algorithm using dynamic bounding volume tree.
- * @author saharan
- * @author lo-th
- */
- OIMO.DBVTBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_BOUNDING_VOLUME_TREE;
- this.tree = new OIMO.DBVT();
- this.stack = [];
- this.leaves = [];
- this.numLeaves = 0;
- };
- OIMO.DBVTBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.DBVTBroadPhase.prototype.constructor = OIMO.DBVTBroadPhase;
- OIMO.DBVTBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.DBVTProxy(shape);
- };
- OIMO.DBVTBroadPhase.prototype.addProxy = function (proxy) {
- this.tree.insertLeaf(proxy.leaf);
- this.leaves.push(proxy.leaf);
- this.numLeaves++;
- };
- OIMO.DBVTBroadPhase.prototype.removeProxy = function (proxy) {
- this.tree.deleteLeaf(proxy.leaf);
- var n = this.leaves.indexOf(proxy.leaf);
- if (n > -1) {
- this.leaves.splice(n, 1);
- this.numLeaves--;
- }
- };
- OIMO.DBVTBroadPhase.prototype.collectPairs = function () {
- if (this.numLeaves < 2) return;
- var leaf, margin = 0.1, i = this.numLeaves;
- while (i--) {
- leaf = this.leaves[i];
- if (leaf.proxy.aabb.intersectTestTwo(leaf.aabb)) {
- leaf.aabb.copy(leaf.proxy.aabb, margin);
- this.tree.deleteLeaf(leaf);
- this.tree.insertLeaf(leaf);
- this.collide(leaf, this.tree.root);
- }
- }
- };
- OIMO.DBVTBroadPhase.prototype.collide = function (node1, node2) {
- var stackCount = 2;
- var s1, s2, n1, n2, l1, l2;
- this.stack[0] = node1;
- this.stack[1] = node2;
- while (stackCount > 0) {
- n1 = this.stack[--stackCount];
- n2 = this.stack[--stackCount];
- l1 = n1.proxy != null;
- l2 = n2.proxy != null;
- this.numPairChecks++;
- if (l1 && l2) {
- s1 = n1.proxy.shape;
- s2 = n2.proxy.shape;
- if (s1 == s2 || s1.aabb.intersectTest(s2.aabb) || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- } else {
- if (n1.aabb.intersectTest(n2.aabb)) continue;
- /*if(stackCount+4>=this.maxStack){// expand the stack
- //this.maxStack<<=1;
- this.maxStack*=2;
- var newStack = [];// vector
- newStack.length = this.maxStack;
- for(var i=0;i<stackCount;i++){
- newStack[i] = this.stack[i];
- }
- this.stack = newStack;
- }*/
- if (l2 || !l1 && (n1.aabb.surfaceArea() > n2.aabb.surfaceArea())) {
- this.stack[stackCount++] = n1.child1;
- this.stack[stackCount++] = n2;
- this.stack[stackCount++] = n1.child2;
- this.stack[stackCount++] = n2;
- } else {
- this.stack[stackCount++] = n1;
- this.stack[stackCount++] = n2.child1;
- this.stack[stackCount++] = n1;
- this.stack[stackCount++] = n2.child2;
- }
- }
- }
- };
- /**
- * A node of the dynamic bounding volume tree.
- * @author saharan
- */
- OIMO.DBVTNode = function () {
- // The first child node of this node.
- this.child1 = null;
- // The second child node of this node.
- this.child2 = null;
- // The parent node of this tree.
- this.parent = null;
- // The proxy of this node. This has no value if this node is not leaf.
- this.proxy = null;
- // The maximum distance from leaf nodes.
- this.height = 0;
- // The AABB of this node.
- this.aabb = new OIMO.AABB();
- };
- /**
- * A proxy for dynamic bounding volume tree broad-phase.
- * @author saharan
- */
- OIMO.DBVTProxy = function (shape) {
- OIMO.Proxy.call(this, shape);
- // The leaf of the proxy.
- this.leaf = new OIMO.DBVTNode();
- this.leaf.proxy = this;
- };
- OIMO.DBVTProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.DBVTProxy.prototype.constructor = OIMO.DBVTProxy;
- OIMO.DBVTProxy.prototype.update = function () {
- };
- OIMO.World.prototype.add = function (obj) {
- obj = obj || {};
- var type = obj.type || "box";
- if (typeof type === 'string') type = [type];// single shape
- if (type[0].substring(0, 5) == 'joint') { // is joint
- if (type[0] === 'joint') type[0] = 'jointHinge';
- var axe1 = obj.axe1 || [1, 0, 0];
- var axe2 = obj.axe2 || [1, 0, 0];
- var pos1 = obj.pos1 || [0, 0, 0];
- var pos2 = obj.pos2 || [0, 0, 0];
- pos1 = pos1.map(function (x) { return x * OIMO.INV_SCALE; });
- pos2 = pos2.map(function (x) { return x * OIMO.INV_SCALE; });
- var min, max;
- if (type[0] === "jointDistance") {
- min = obj.min || 0;
- max = obj.max || 10;
- min = min * OIMO.INV_SCALE;
- max = max * OIMO.INV_SCALE;
- } else {
- min = obj.min || 57.29578;
- max = obj.max || 0;
- min = min * OIMO.degtorad;
- max = max * OIMO.degtorad;
- }
- var limit = obj.limit || null;
- var spring = obj.spring || null;
- var motor = obj.motor || null;
- // joint setting
- var jc = new OIMO.JointConfig();
- jc.allowCollision = obj.collision || false;;
- jc.localAxis1.init(axe1[0], axe1[1], axe1[2]);
- jc.localAxis2.init(axe2[0], axe2[1], axe2[2]);
- jc.localAnchorPoint1.init(pos1[0], pos1[1], pos1[2]);
- jc.localAnchorPoint2.init(pos2[0], pos2[1], pos2[2]);
- if (typeof obj.body1 == 'string' || obj.body1 instanceof String) obj.body1 = this.getByName(obj.body1);
- if (typeof obj.body2 == 'string' || obj.body2 instanceof String) obj.body2 = this.getByName(obj.body2);
- jc.body1 = obj.body1;
- jc.body2 = obj.body2;
- var joint;
- switch (type[0]) {
- case "jointDistance": joint = new OIMO.DistanceJoint(jc, min, max);
- if (spring !== null) joint.limitMotor.setSpring(spring[0], spring[1]);
- if (motor !== null) joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointHinge": joint = new OIMO.HingeJoint(jc, min, max);
- if (spring !== null) joint.limitMotor.setSpring(spring[0], spring[1]);// soften the joint ex: 100, 0.2
- if (motor !== null) joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointPrisme": joint = new OIMO.PrismaticJoint(jc, min, max); break;
- case "jointSlide": joint = new OIMO.SliderJoint(jc, min, max); break;
- case "jointBall": joint = new OIMO.BallAndSocketJoint(jc); break;
- case "jointWheel": joint = new OIMO.WheelJoint(jc);
- if (limit !== null) joint.rotationalLimitMotor1.setLimit(limit[0], limit[1]);
- if (spring !== null) joint.rotationalLimitMotor1.setSpring(spring[0], spring[1]);
- if (motor !== null) joint.rotationalLimitMotor1.setSpring(motor[0], motor[1]);
- break;
- }
- joint.name = obj.name || '';
- // finaly add to physics world
- this.addJoint(joint);
- return joint;
- } else { // is body
- // I'm dynamique or not
- var move = obj.move || false;
- // I can sleep or not
- var noSleep = obj.noSleep || false;
- // My start position
- var p = obj.pos || [0, 0, 0];
- p = p.map(function (x) { return x * OIMO.INV_SCALE; });
- // My size
- var s = obj.size || [1, 1, 1];
- s = s.map(function (x) { return x * OIMO.INV_SCALE; });
- // My rotation in degre
- var rot = obj.rot || [0, 0, 0];
- rot = rot.map(function (x) { return x * OIMO.degtorad; });
- var r = [];
- for (var i = 0; i < rot.length / 3; i++) {
- var tmp = OIMO.EulerToAxis(rot[i + 0], rot[i + 1], rot[i + 2]);
- r.push(tmp[0]); r.push(tmp[1]); r.push(tmp[2]); r.push(tmp[3]);
- }
- // My physics setting
- var sc = new OIMO.ShapeConfig();
- if (obj.sc !== undefined) sc = obj.sc;
- if (obj.config) {
- // The density of the shape.
- sc.density = obj.config[0] === undefined ? 1 : obj.config[0];
- // The coefficient of friction of the shape.
- sc.friction = obj.config[1] === undefined ? 0.4 : obj.config[1];
- // The coefficient of restitution of the shape.
- sc.restitution = obj.config[2] === undefined ? 0.2 : obj.config[2];
- // The bits of the collision groups to which the shape belongs.
- sc.belongsTo = obj.config[3] || 1;
- //sc.belongsTo = obj.config[3] === undefined ? 1 : obj.config[3];
- // The bits of the collision groups with which the shape collides.
- sc.collidesWith = obj.config[4] || 0xffffffff;
- //sc.collidesWith = obj.config[4] === undefined ? 0xffffffff : obj.config[4];
- }
- // direct physics setting
- if (obj.density !== undefined) sc.density = obj.density;
- if (obj.friction !== undefined) sc.friction = obj.friction;
- if (obj.restitution !== undefined) sc.restitution = obj.restitution;
- if (obj.belongsTo !== undefined) sc.belongsTo = obj.belongsTo;
- if (obj.collidesWith !== undefined) sc.collidesWith = obj.collidesWith;
- if (obj.massPos) {
- obj.massPos = obj.massPos.map(function (x) { return x * OIMO.INV_SCALE; });
- sc.relativePosition.init(obj.massPos[0], obj.massPos[1], obj.massPos[2]);
- }
- if (obj.massRot) {
- obj.massRot = obj.massRot.map(function (x) { return x * OIMO.degtorad; });
- sc.relativeRotation = OIMO.EulerToMatrix(obj.massRot[0], obj.massRot[1], obj.massRot[2]);
- }
- // My rigidbody
- var body = new OIMO.RigidBody(p[0], p[1], p[2], r[0], r[1], r[2], r[3]);
- // My shapes
- var shapes = [];
- //if( typeof type === 'string' ) type = [type];// single shape
- var n, n2;
- for (var i = 0; i < type.length; i++) {
- n = i * 3;
- n2 = i * 4;
- switch (type[i]) {
- case "sphere": shapes[i] = new OIMO.SphereShape(sc, s[n]); break;
- case "cylinder": shapes[i] = new OIMO.CylinderShape(sc, s[n], s[n + 1]); break;
- case "box": shapes[i] = new OIMO.BoxShape(sc, s[n], s[n + 1], s[n + 2]); break;
- }
- body.addShape(shapes[i]);
- if (i > 0) {
- //shapes[i].position.init(p[0]+p[n+0], p[1]+p[n+1], p[2]+p[n+2] );
- shapes[i].relativePosition = new OIMO.Vec3(p[n], p[n + 1], p[n + 2]);
- if (r[n2 + 0]) shapes[i].relativeRotation = [r[n2], r[n2 + 1], r[n2 + 2], r[n2 + 3]];
- }
- }
- // I'm static or i move
- if (move) {
- if (obj.massPos || obj.massRot) body.setupMass(0x1, false);
- else body.setupMass(0x1, true);
- if (noSleep) body.allowSleep = false;
- else body.allowSleep = true;
- } else {
- body.setupMass(0x2);
- }
- body.name = obj.name || ' ';
- // finaly add to physics world
- this.addRigidBody(body);
- return body;
- }
- }
- //UMD simplified
- var root = this;
- if (!root['OIMO']) {
- if (typeof exports === 'object' && typeof module === 'object')
- module.exports = OIMO;
- else if (typeof define === 'function' && define.amd)
- define([], function () {
- return OIMO;
- });
- else if (typeof exports === 'object')
- exports["OIMO"] = OIMO;
- else {
- root["OIMO"] = OIMO;
- }
- }
|