cannon.js 386 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734
  1. /*
  2. * Copyright (c) 2015 cannon.js Authors
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. !function(e){if("object"==typeof exports&&"undefined"!=typeof module&&false)module.exports=e();else if("function"==typeof define&&false)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.CANNON=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  24. module.exports={
  25. "name": "cannon",
  26. "version": "0.6.2",
  27. "description": "A lightweight 3D physics engine written in JavaScript.",
  28. "homepage": "https://github.com/schteppe/cannon.js",
  29. "author": "Stefan Hedman <schteppe@gmail.com> (http://steffe.se)",
  30. "keywords": [
  31. "cannon.js",
  32. "cannon",
  33. "physics",
  34. "engine",
  35. "3d"
  36. ],
  37. "main": "./build/cannon.js",
  38. "engines": {
  39. "node": "*"
  40. },
  41. "repository": {
  42. "type": "git",
  43. "url": "https://github.com/schteppe/cannon.js.git"
  44. },
  45. "bugs": {
  46. "url": "https://github.com/schteppe/cannon.js/issues"
  47. },
  48. "licenses": [
  49. {
  50. "type": "MIT"
  51. }
  52. ],
  53. "devDependencies": {
  54. "jshint": "latest",
  55. "uglify-js": "latest",
  56. "nodeunit": "^0.9.0",
  57. "grunt": "~0.4.0",
  58. "grunt-contrib-jshint": "~0.1.1",
  59. "grunt-contrib-nodeunit": "^0.4.1",
  60. "grunt-contrib-concat": "~0.1.3",
  61. "grunt-contrib-uglify": "^0.5.1",
  62. "grunt-browserify": "^2.1.4",
  63. "grunt-contrib-yuidoc": "^0.5.2",
  64. "browserify": "*"
  65. },
  66. "dependencies": {}
  67. }
  68. },{}],2:[function(_dereq_,module,exports){
  69. // Export classes
  70. module.exports = {
  71. version : _dereq_('../package.json').version,
  72. AABB : _dereq_('./collision/AABB'),
  73. ArrayCollisionMatrix : _dereq_('./collision/ArrayCollisionMatrix'),
  74. Body : _dereq_('./objects/Body'),
  75. Box : _dereq_('./shapes/Box'),
  76. Broadphase : _dereq_('./collision/Broadphase'),
  77. Constraint : _dereq_('./constraints/Constraint'),
  78. ContactEquation : _dereq_('./equations/ContactEquation'),
  79. Narrowphase : _dereq_('./world/Narrowphase'),
  80. ConeTwistConstraint : _dereq_('./constraints/ConeTwistConstraint'),
  81. ContactMaterial : _dereq_('./material/ContactMaterial'),
  82. ConvexPolyhedron : _dereq_('./shapes/ConvexPolyhedron'),
  83. Cylinder : _dereq_('./shapes/Cylinder'),
  84. DistanceConstraint : _dereq_('./constraints/DistanceConstraint'),
  85. Equation : _dereq_('./equations/Equation'),
  86. EventTarget : _dereq_('./utils/EventTarget'),
  87. FrictionEquation : _dereq_('./equations/FrictionEquation'),
  88. GSSolver : _dereq_('./solver/GSSolver'),
  89. GridBroadphase : _dereq_('./collision/GridBroadphase'),
  90. Heightfield : _dereq_('./shapes/Heightfield'),
  91. HingeConstraint : _dereq_('./constraints/HingeConstraint'),
  92. LockConstraint : _dereq_('./constraints/LockConstraint'),
  93. Mat3 : _dereq_('./math/Mat3'),
  94. Material : _dereq_('./material/Material'),
  95. NaiveBroadphase : _dereq_('./collision/NaiveBroadphase'),
  96. ObjectCollisionMatrix : _dereq_('./collision/ObjectCollisionMatrix'),
  97. Pool : _dereq_('./utils/Pool'),
  98. Particle : _dereq_('./shapes/Particle'),
  99. Plane : _dereq_('./shapes/Plane'),
  100. PointToPointConstraint : _dereq_('./constraints/PointToPointConstraint'),
  101. Quaternion : _dereq_('./math/Quaternion'),
  102. Ray : _dereq_('./collision/Ray'),
  103. RaycastVehicle : _dereq_('./objects/RaycastVehicle'),
  104. RaycastResult : _dereq_('./collision/RaycastResult'),
  105. RigidVehicle : _dereq_('./objects/RigidVehicle'),
  106. RotationalEquation : _dereq_('./equations/RotationalEquation'),
  107. RotationalMotorEquation : _dereq_('./equations/RotationalMotorEquation'),
  108. SAPBroadphase : _dereq_('./collision/SAPBroadphase'),
  109. SPHSystem : _dereq_('./objects/SPHSystem'),
  110. Shape : _dereq_('./shapes/Shape'),
  111. Solver : _dereq_('./solver/Solver'),
  112. Sphere : _dereq_('./shapes/Sphere'),
  113. SplitSolver : _dereq_('./solver/SplitSolver'),
  114. Spring : _dereq_('./objects/Spring'),
  115. Trimesh : _dereq_('./shapes/Trimesh'),
  116. Vec3 : _dereq_('./math/Vec3'),
  117. Vec3Pool : _dereq_('./utils/Vec3Pool'),
  118. World : _dereq_('./world/World'),
  119. };
  120. },{"../package.json":1,"./collision/AABB":3,"./collision/ArrayCollisionMatrix":4,"./collision/Broadphase":5,"./collision/GridBroadphase":6,"./collision/NaiveBroadphase":7,"./collision/ObjectCollisionMatrix":8,"./collision/Ray":9,"./collision/RaycastResult":10,"./collision/SAPBroadphase":11,"./constraints/ConeTwistConstraint":12,"./constraints/Constraint":13,"./constraints/DistanceConstraint":14,"./constraints/HingeConstraint":15,"./constraints/LockConstraint":16,"./constraints/PointToPointConstraint":17,"./equations/ContactEquation":19,"./equations/Equation":20,"./equations/FrictionEquation":21,"./equations/RotationalEquation":22,"./equations/RotationalMotorEquation":23,"./material/ContactMaterial":24,"./material/Material":25,"./math/Mat3":27,"./math/Quaternion":28,"./math/Vec3":30,"./objects/Body":31,"./objects/RaycastVehicle":32,"./objects/RigidVehicle":33,"./objects/SPHSystem":34,"./objects/Spring":35,"./shapes/Box":37,"./shapes/ConvexPolyhedron":38,"./shapes/Cylinder":39,"./shapes/Heightfield":40,"./shapes/Particle":41,"./shapes/Plane":42,"./shapes/Shape":43,"./shapes/Sphere":44,"./shapes/Trimesh":45,"./solver/GSSolver":46,"./solver/Solver":47,"./solver/SplitSolver":48,"./utils/EventTarget":49,"./utils/Pool":51,"./utils/Vec3Pool":54,"./world/Narrowphase":55,"./world/World":56}],3:[function(_dereq_,module,exports){
  121. var Vec3 = _dereq_('../math/Vec3');
  122. var Utils = _dereq_('../utils/Utils');
  123. module.exports = AABB;
  124. /**
  125. * Axis aligned bounding box class.
  126. * @class AABB
  127. * @constructor
  128. * @param {Object} [options]
  129. * @param {Vec3} [options.upperBound]
  130. * @param {Vec3} [options.lowerBound]
  131. */
  132. function AABB(options){
  133. options = options || {};
  134. /**
  135. * The lower bound of the bounding box.
  136. * @property lowerBound
  137. * @type {Vec3}
  138. */
  139. this.lowerBound = new Vec3();
  140. if(options.lowerBound){
  141. this.lowerBound.copy(options.lowerBound);
  142. }
  143. /**
  144. * The upper bound of the bounding box.
  145. * @property upperBound
  146. * @type {Vec3}
  147. */
  148. this.upperBound = new Vec3();
  149. if(options.upperBound){
  150. this.upperBound.copy(options.upperBound);
  151. }
  152. }
  153. var tmp = new Vec3();
  154. /**
  155. * Set the AABB bounds from a set of points.
  156. * @method setFromPoints
  157. * @param {Array} points An array of Vec3's.
  158. * @param {Vec3} position
  159. * @param {Quaternion} quaternion
  160. * @param {number} skinSize
  161. * @return {AABB} The self object
  162. */
  163. AABB.prototype.setFromPoints = function(points, position, quaternion, skinSize){
  164. var l = this.lowerBound,
  165. u = this.upperBound,
  166. q = quaternion;
  167. // Set to the first point
  168. l.copy(points[0]);
  169. if(q){
  170. q.vmult(l, l);
  171. }
  172. u.copy(l);
  173. for(var i = 1; i<points.length; i++){
  174. var p = points[i];
  175. if(q){
  176. q.vmult(p, tmp);
  177. p = tmp;
  178. }
  179. if(p.x > u.x){ u.x = p.x; }
  180. if(p.x < l.x){ l.x = p.x; }
  181. if(p.y > u.y){ u.y = p.y; }
  182. if(p.y < l.y){ l.y = p.y; }
  183. if(p.z > u.z){ u.z = p.z; }
  184. if(p.z < l.z){ l.z = p.z; }
  185. }
  186. // Add offset
  187. if (position) {
  188. position.vadd(l, l);
  189. position.vadd(u, u);
  190. }
  191. if(skinSize){
  192. l.x -= skinSize;
  193. l.y -= skinSize;
  194. l.z -= skinSize;
  195. u.x += skinSize;
  196. u.y += skinSize;
  197. u.z += skinSize;
  198. }
  199. return this;
  200. };
  201. /**
  202. * Copy bounds from an AABB to this AABB
  203. * @method copy
  204. * @param {AABB} aabb Source to copy from
  205. * @return {AABB} The this object, for chainability
  206. */
  207. AABB.prototype.copy = function(aabb){
  208. this.lowerBound.copy(aabb.lowerBound);
  209. this.upperBound.copy(aabb.upperBound);
  210. return this;
  211. };
  212. /**
  213. * Clone an AABB
  214. * @method clone
  215. */
  216. AABB.prototype.clone = function(){
  217. return new AABB().copy(this);
  218. };
  219. /**
  220. * Extend this AABB so that it covers the given AABB too.
  221. * @method extend
  222. * @param {AABB} aabb
  223. */
  224. AABB.prototype.extend = function(aabb){
  225. // Extend lower bound
  226. var l = aabb.lowerBound.x;
  227. if(this.lowerBound.x > l){
  228. this.lowerBound.x = l;
  229. }
  230. // Upper
  231. var u = aabb.upperBound.x;
  232. if(this.upperBound.x < u){
  233. this.upperBound.x = u;
  234. }
  235. // Extend lower bound
  236. var l = aabb.lowerBound.y;
  237. if(this.lowerBound.y > l){
  238. this.lowerBound.y = l;
  239. }
  240. // Upper
  241. var u = aabb.upperBound.y;
  242. if(this.upperBound.y < u){
  243. this.upperBound.y = u;
  244. }
  245. // Extend lower bound
  246. var l = aabb.lowerBound.z;
  247. if(this.lowerBound.z > l){
  248. this.lowerBound.z = l;
  249. }
  250. // Upper
  251. var u = aabb.upperBound.z;
  252. if(this.upperBound.z < u){
  253. this.upperBound.z = u;
  254. }
  255. };
  256. /**
  257. * Returns true if the given AABB overlaps this AABB.
  258. * @method overlaps
  259. * @param {AABB} aabb
  260. * @return {Boolean}
  261. */
  262. AABB.prototype.overlaps = function(aabb){
  263. var l1 = this.lowerBound,
  264. u1 = this.upperBound,
  265. l2 = aabb.lowerBound,
  266. u2 = aabb.upperBound;
  267. // l2 u2
  268. // |---------|
  269. // |--------|
  270. // l1 u1
  271. return ((l2.x <= u1.x && u1.x <= u2.x) || (l1.x <= u2.x && u2.x <= u1.x)) &&
  272. ((l2.y <= u1.y && u1.y <= u2.y) || (l1.y <= u2.y && u2.y <= u1.y)) &&
  273. ((l2.z <= u1.z && u1.z <= u2.z) || (l1.z <= u2.z && u2.z <= u1.z));
  274. };
  275. /**
  276. * Returns true if the given AABB is fully contained in this AABB.
  277. * @method contains
  278. * @param {AABB} aabb
  279. * @return {Boolean}
  280. */
  281. AABB.prototype.contains = function(aabb){
  282. var l1 = this.lowerBound,
  283. u1 = this.upperBound,
  284. l2 = aabb.lowerBound,
  285. u2 = aabb.upperBound;
  286. // l2 u2
  287. // |---------|
  288. // |---------------|
  289. // l1 u1
  290. return (
  291. (l1.x <= l2.x && u1.x >= u2.x) &&
  292. (l1.y <= l2.y && u1.y >= u2.y) &&
  293. (l1.z <= l2.z && u1.z >= u2.z)
  294. );
  295. };
  296. /**
  297. * @method getCorners
  298. * @param {Vec3} a
  299. * @param {Vec3} b
  300. * @param {Vec3} c
  301. * @param {Vec3} d
  302. * @param {Vec3} e
  303. * @param {Vec3} f
  304. * @param {Vec3} g
  305. * @param {Vec3} h
  306. */
  307. AABB.prototype.getCorners = function(a, b, c, d, e, f, g, h){
  308. var l = this.lowerBound,
  309. u = this.upperBound;
  310. a.copy(l);
  311. b.set( u.x, l.y, l.z );
  312. c.set( u.x, u.y, l.z );
  313. d.set( l.x, u.y, u.z );
  314. e.set( u.x, l.y, l.z );
  315. f.set( l.x, u.y, l.z );
  316. g.set( l.x, l.y, u.z );
  317. h.copy(u);
  318. };
  319. var transformIntoFrame_corners = [
  320. new Vec3(),
  321. new Vec3(),
  322. new Vec3(),
  323. new Vec3(),
  324. new Vec3(),
  325. new Vec3(),
  326. new Vec3(),
  327. new Vec3()
  328. ];
  329. /**
  330. * Get the representation of an AABB in another frame.
  331. * @method toLocalFrame
  332. * @param {Transform} frame
  333. * @param {AABB} target
  334. * @return {AABB} The "target" AABB object.
  335. */
  336. AABB.prototype.toLocalFrame = function(frame, target){
  337. var corners = transformIntoFrame_corners;
  338. var a = corners[0];
  339. var b = corners[1];
  340. var c = corners[2];
  341. var d = corners[3];
  342. var e = corners[4];
  343. var f = corners[5];
  344. var g = corners[6];
  345. var h = corners[7];
  346. // Get corners in current frame
  347. this.getCorners(a, b, c, d, e, f, g, h);
  348. // Transform them to new local frame
  349. for(var i=0; i !== 8; i++){
  350. var corner = corners[i];
  351. frame.pointToLocal(corner, corner);
  352. }
  353. return target.setFromPoints(corners);
  354. };
  355. /**
  356. * Get the representation of an AABB in the global frame.
  357. * @method toWorldFrame
  358. * @param {Transform} frame
  359. * @param {AABB} target
  360. * @return {AABB} The "target" AABB object.
  361. */
  362. AABB.prototype.toWorldFrame = function(frame, target){
  363. var corners = transformIntoFrame_corners;
  364. var a = corners[0];
  365. var b = corners[1];
  366. var c = corners[2];
  367. var d = corners[3];
  368. var e = corners[4];
  369. var f = corners[5];
  370. var g = corners[6];
  371. var h = corners[7];
  372. // Get corners in current frame
  373. this.getCorners(a, b, c, d, e, f, g, h);
  374. // Transform them to new local frame
  375. for(var i=0; i !== 8; i++){
  376. var corner = corners[i];
  377. frame.pointToWorld(corner, corner);
  378. }
  379. return target.setFromPoints(corners);
  380. };
  381. },{"../math/Vec3":30,"../utils/Utils":53}],4:[function(_dereq_,module,exports){
  382. module.exports = ArrayCollisionMatrix;
  383. /**
  384. * Collision "matrix". It's actually a triangular-shaped array of whether two bodies are touching this step, for reference next step
  385. * @class ArrayCollisionMatrix
  386. * @constructor
  387. */
  388. function ArrayCollisionMatrix() {
  389. /**
  390. * The matrix storage
  391. * @property matrix
  392. * @type {Array}
  393. */
  394. this.matrix = [];
  395. }
  396. /**
  397. * Get an element
  398. * @method get
  399. * @param {Number} i
  400. * @param {Number} j
  401. * @return {Number}
  402. */
  403. ArrayCollisionMatrix.prototype.get = function(i, j) {
  404. i = i.index;
  405. j = j.index;
  406. if (j > i) {
  407. var temp = j;
  408. j = i;
  409. i = temp;
  410. }
  411. return this.matrix[(i*(i + 1)>>1) + j-1];
  412. };
  413. /**
  414. * Set an element
  415. * @method set
  416. * @param {Number} i
  417. * @param {Number} j
  418. * @param {Number} value
  419. */
  420. ArrayCollisionMatrix.prototype.set = function(i, j, value) {
  421. i = i.index;
  422. j = j.index;
  423. if (j > i) {
  424. var temp = j;
  425. j = i;
  426. i = temp;
  427. }
  428. this.matrix[(i*(i + 1)>>1) + j-1] = value ? 1 : 0;
  429. };
  430. /**
  431. * Sets all elements to zero
  432. * @method reset
  433. */
  434. ArrayCollisionMatrix.prototype.reset = function() {
  435. for (var i=0, l=this.matrix.length; i!==l; i++) {
  436. this.matrix[i]=0;
  437. }
  438. };
  439. /**
  440. * Sets the max number of objects
  441. * @method setNumObjects
  442. * @param {Number} n
  443. */
  444. ArrayCollisionMatrix.prototype.setNumObjects = function(n) {
  445. this.matrix.length = n*(n-1)>>1;
  446. };
  447. },{}],5:[function(_dereq_,module,exports){
  448. var Body = _dereq_('../objects/Body');
  449. var Vec3 = _dereq_('../math/Vec3');
  450. var Quaternion = _dereq_('../math/Quaternion');
  451. var Shape = _dereq_('../shapes/Shape');
  452. var Plane = _dereq_('../shapes/Plane');
  453. module.exports = Broadphase;
  454. /**
  455. * Base class for broadphase implementations
  456. * @class Broadphase
  457. * @constructor
  458. * @author schteppe
  459. */
  460. function Broadphase(){
  461. /**
  462. * The world to search for collisions in.
  463. * @property world
  464. * @type {World}
  465. */
  466. this.world = null;
  467. /**
  468. * If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres.
  469. * @property useBoundingBoxes
  470. * @type {Boolean}
  471. */
  472. this.useBoundingBoxes = false;
  473. /**
  474. * Set to true if the objects in the world moved.
  475. * @property {Boolean} dirty
  476. */
  477. this.dirty = true;
  478. }
  479. /**
  480. * Get the collision pairs from the world
  481. * @method collisionPairs
  482. * @param {World} world The world to search in
  483. * @param {Array} p1 Empty array to be filled with body objects
  484. * @param {Array} p2 Empty array to be filled with body objects
  485. */
  486. Broadphase.prototype.collisionPairs = function(world,p1,p2){
  487. throw new Error("collisionPairs not implemented for this BroadPhase class!");
  488. };
  489. /**
  490. * Check if a body pair needs to be intersection tested at all.
  491. * @method needBroadphaseCollision
  492. * @param {Body} bodyA
  493. * @param {Body} bodyB
  494. * @return {bool}
  495. */
  496. var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = Body.STATIC | Body.KINEMATIC;
  497. Broadphase.prototype.needBroadphaseCollision = function(bodyA,bodyB){
  498. // Check collision filter masks
  499. if( (bodyA.collisionFilterGroup & bodyB.collisionFilterMask)===0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)===0){
  500. return false;
  501. }
  502. // Check types
  503. if(((bodyA.type & Body.STATIC)!==0 || bodyA.sleepState === Body.SLEEPING) &&
  504. ((bodyB.type & Body.STATIC)!==0 || bodyB.sleepState === Body.SLEEPING)) {
  505. // Both bodies are static, kinematic or sleeping. Skip.
  506. return false;
  507. }
  508. return true;
  509. };
  510. /**
  511. * Check if the bounding volumes of two bodies intersect.
  512. * @method intersectionTest
  513. * @param {Body} bodyA
  514. * @param {Body} bodyB
  515. * @param {array} pairs1
  516. * @param {array} pairs2
  517. */
  518. Broadphase.prototype.intersectionTest = function(bodyA, bodyB, pairs1, pairs2){
  519. if(this.useBoundingBoxes){
  520. this.doBoundingBoxBroadphase(bodyA,bodyB,pairs1,pairs2);
  521. } else {
  522. this.doBoundingSphereBroadphase(bodyA,bodyB,pairs1,pairs2);
  523. }
  524. };
  525. /**
  526. * Check if the bounding spheres of two bodies are intersecting.
  527. * @method doBoundingSphereBroadphase
  528. * @param {Body} bodyA
  529. * @param {Body} bodyB
  530. * @param {Array} pairs1 bodyA is appended to this array if intersection
  531. * @param {Array} pairs2 bodyB is appended to this array if intersection
  532. */
  533. var Broadphase_collisionPairs_r = new Vec3(), // Temp objects
  534. Broadphase_collisionPairs_normal = new Vec3(),
  535. Broadphase_collisionPairs_quat = new Quaternion(),
  536. Broadphase_collisionPairs_relpos = new Vec3();
  537. Broadphase.prototype.doBoundingSphereBroadphase = function(bodyA,bodyB,pairs1,pairs2){
  538. var r = Broadphase_collisionPairs_r;
  539. bodyB.position.vsub(bodyA.position,r);
  540. var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2);
  541. var norm2 = r.norm2();
  542. if(norm2 < boundingRadiusSum2){
  543. pairs1.push(bodyA);
  544. pairs2.push(bodyB);
  545. }
  546. };
  547. /**
  548. * Check if the bounding boxes of two bodies are intersecting.
  549. * @method doBoundingBoxBroadphase
  550. * @param {Body} bodyA
  551. * @param {Body} bodyB
  552. * @param {Array} pairs1
  553. * @param {Array} pairs2
  554. */
  555. Broadphase.prototype.doBoundingBoxBroadphase = function(bodyA,bodyB,pairs1,pairs2){
  556. if(bodyA.aabbNeedsUpdate){
  557. bodyA.computeAABB();
  558. }
  559. if(bodyB.aabbNeedsUpdate){
  560. bodyB.computeAABB();
  561. }
  562. // Check AABB / AABB
  563. if(bodyA.aabb.overlaps(bodyB.aabb)){
  564. pairs1.push(bodyA);
  565. pairs2.push(bodyB);
  566. }
  567. };
  568. /**
  569. * Removes duplicate pairs from the pair arrays.
  570. * @method makePairsUnique
  571. * @param {Array} pairs1
  572. * @param {Array} pairs2
  573. */
  574. var Broadphase_makePairsUnique_temp = { keys:[] },
  575. Broadphase_makePairsUnique_p1 = [],
  576. Broadphase_makePairsUnique_p2 = [];
  577. Broadphase.prototype.makePairsUnique = function(pairs1,pairs2){
  578. var t = Broadphase_makePairsUnique_temp,
  579. p1 = Broadphase_makePairsUnique_p1,
  580. p2 = Broadphase_makePairsUnique_p2,
  581. N = pairs1.length;
  582. for(var i=0; i!==N; i++){
  583. p1[i] = pairs1[i];
  584. p2[i] = pairs2[i];
  585. }
  586. pairs1.length = 0;
  587. pairs2.length = 0;
  588. for(var i=0; i!==N; i++){
  589. var id1 = p1[i].id,
  590. id2 = p2[i].id;
  591. var key = id1 < id2 ? id1+","+id2 : id2+","+id1;
  592. t[key] = i;
  593. t.keys.push(key);
  594. }
  595. for(var i=0; i!==t.keys.length; i++){
  596. var key = t.keys.pop(),
  597. pairIndex = t[key];
  598. pairs1.push(p1[pairIndex]);
  599. pairs2.push(p2[pairIndex]);
  600. delete t[key];
  601. }
  602. };
  603. /**
  604. * To be implemented by subcasses
  605. * @method setWorld
  606. * @param {World} world
  607. */
  608. Broadphase.prototype.setWorld = function(world){
  609. };
  610. /**
  611. * Check if the bounding spheres of two bodies overlap.
  612. * @method boundingSphereCheck
  613. * @param {Body} bodyA
  614. * @param {Body} bodyB
  615. * @return {boolean}
  616. */
  617. var bsc_dist = new Vec3();
  618. Broadphase.boundingSphereCheck = function(bodyA,bodyB){
  619. var dist = bsc_dist;
  620. bodyA.position.vsub(bodyB.position,dist);
  621. return Math.pow(bodyA.shape.boundingSphereRadius + bodyB.shape.boundingSphereRadius,2) > dist.norm2();
  622. };
  623. /**
  624. * Returns all the bodies within the AABB.
  625. * @method aabbQuery
  626. * @param {World} world
  627. * @param {AABB} aabb
  628. * @param {array} result An array to store resulting bodies in.
  629. * @return {array}
  630. */
  631. Broadphase.prototype.aabbQuery = function(world, aabb, result){
  632. console.warn('.aabbQuery is not implemented in this Broadphase subclass.');
  633. return [];
  634. };
  635. },{"../math/Quaternion":28,"../math/Vec3":30,"../objects/Body":31,"../shapes/Plane":42,"../shapes/Shape":43}],6:[function(_dereq_,module,exports){
  636. module.exports = GridBroadphase;
  637. var Broadphase = _dereq_('./Broadphase');
  638. var Vec3 = _dereq_('../math/Vec3');
  639. var Shape = _dereq_('../shapes/Shape');
  640. /**
  641. * Axis aligned uniform grid broadphase.
  642. * @class GridBroadphase
  643. * @constructor
  644. * @extends Broadphase
  645. * @todo Needs support for more than just planes and spheres.
  646. * @param {Vec3} aabbMin
  647. * @param {Vec3} aabbMax
  648. * @param {Number} nx Number of boxes along x
  649. * @param {Number} ny Number of boxes along y
  650. * @param {Number} nz Number of boxes along z
  651. */
  652. function GridBroadphase(aabbMin,aabbMax,nx,ny,nz){
  653. Broadphase.apply(this);
  654. this.nx = nx || 10;
  655. this.ny = ny || 10;
  656. this.nz = nz || 10;
  657. this.aabbMin = aabbMin || new Vec3(100,100,100);
  658. this.aabbMax = aabbMax || new Vec3(-100,-100,-100);
  659. var nbins = this.nx * this.ny * this.nz;
  660. if (nbins <= 0) {
  661. throw "GridBroadphase: Each dimension's n must be >0";
  662. }
  663. this.bins = [];
  664. this.binLengths = []; //Rather than continually resizing arrays (thrashing the memory), just record length and allow them to grow
  665. this.bins.length = nbins;
  666. this.binLengths.length = nbins;
  667. for (var i=0;i<nbins;i++) {
  668. this.bins[i]=[];
  669. this.binLengths[i]=0;
  670. }
  671. }
  672. GridBroadphase.prototype = new Broadphase();
  673. GridBroadphase.prototype.constructor = GridBroadphase;
  674. /**
  675. * Get all the collision pairs in the physics world
  676. * @method collisionPairs
  677. * @param {World} world
  678. * @param {Array} pairs1
  679. * @param {Array} pairs2
  680. */
  681. var GridBroadphase_collisionPairs_d = new Vec3();
  682. var GridBroadphase_collisionPairs_binPos = new Vec3();
  683. GridBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){
  684. var N = world.numObjects(),
  685. bodies = world.bodies;
  686. var max = this.aabbMax,
  687. min = this.aabbMin,
  688. nx = this.nx,
  689. ny = this.ny,
  690. nz = this.nz;
  691. var xstep = ny*nz;
  692. var ystep = nz;
  693. var zstep = 1;
  694. var xmax = max.x,
  695. ymax = max.y,
  696. zmax = max.z,
  697. xmin = min.x,
  698. ymin = min.y,
  699. zmin = min.z;
  700. var xmult = nx / (xmax-xmin),
  701. ymult = ny / (ymax-ymin),
  702. zmult = nz / (zmax-zmin);
  703. var binsizeX = (xmax - xmin) / nx,
  704. binsizeY = (ymax - ymin) / ny,
  705. binsizeZ = (zmax - zmin) / nz;
  706. var binRadius = Math.sqrt(binsizeX*binsizeX + binsizeY*binsizeY + binsizeZ*binsizeZ) * 0.5;
  707. var types = Shape.types;
  708. var SPHERE = types.SPHERE,
  709. PLANE = types.PLANE,
  710. BOX = types.BOX,
  711. COMPOUND = types.COMPOUND,
  712. CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON;
  713. var bins=this.bins,
  714. binLengths=this.binLengths,
  715. Nbins=this.bins.length;
  716. // Reset bins
  717. for(var i=0; i!==Nbins; i++){
  718. binLengths[i] = 0;
  719. }
  720. var ceil = Math.ceil;
  721. var min = Math.min;
  722. var max = Math.max;
  723. function addBoxToBins(x0,y0,z0,x1,y1,z1,bi) {
  724. var xoff0 = ((x0 - xmin) * xmult)|0,
  725. yoff0 = ((y0 - ymin) * ymult)|0,
  726. zoff0 = ((z0 - zmin) * zmult)|0,
  727. xoff1 = ceil((x1 - xmin) * xmult),
  728. yoff1 = ceil((y1 - ymin) * ymult),
  729. zoff1 = ceil((z1 - zmin) * zmult);
  730. if (xoff0 < 0) { xoff0 = 0; } else if (xoff0 >= nx) { xoff0 = nx - 1; }
  731. if (yoff0 < 0) { yoff0 = 0; } else if (yoff0 >= ny) { yoff0 = ny - 1; }
  732. if (zoff0 < 0) { zoff0 = 0; } else if (zoff0 >= nz) { zoff0 = nz - 1; }
  733. if (xoff1 < 0) { xoff1 = 0; } else if (xoff1 >= nx) { xoff1 = nx - 1; }
  734. if (yoff1 < 0) { yoff1 = 0; } else if (yoff1 >= ny) { yoff1 = ny - 1; }
  735. if (zoff1 < 0) { zoff1 = 0; } else if (zoff1 >= nz) { zoff1 = nz - 1; }
  736. xoff0 *= xstep;
  737. yoff0 *= ystep;
  738. zoff0 *= zstep;
  739. xoff1 *= xstep;
  740. yoff1 *= ystep;
  741. zoff1 *= zstep;
  742. for (var xoff = xoff0; xoff <= xoff1; xoff += xstep) {
  743. for (var yoff = yoff0; yoff <= yoff1; yoff += ystep) {
  744. for (var zoff = zoff0; zoff <= zoff1; zoff += zstep) {
  745. var idx = xoff+yoff+zoff;
  746. bins[idx][binLengths[idx]++] = bi;
  747. }
  748. }
  749. }
  750. }
  751. // Put all bodies into the bins
  752. for(var i=0; i!==N; i++){
  753. var bi = bodies[i];
  754. var si = bi.shape;
  755. switch(si.type){
  756. case SPHERE:
  757. // Put in bin
  758. // check if overlap with other bins
  759. var x = bi.position.x,
  760. y = bi.position.y,
  761. z = bi.position.z;
  762. var r = si.radius;
  763. addBoxToBins(x-r, y-r, z-r, x+r, y+r, z+r, bi);
  764. break;
  765. case PLANE:
  766. if(si.worldNormalNeedsUpdate){
  767. si.computeWorldNormal(bi.quaternion);
  768. }
  769. var planeNormal = si.worldNormal;
  770. //Relative position from origin of plane object to the first bin
  771. //Incremented as we iterate through the bins
  772. var xreset = xmin + binsizeX*0.5 - bi.position.x,
  773. yreset = ymin + binsizeY*0.5 - bi.position.y,
  774. zreset = zmin + binsizeZ*0.5 - bi.position.z;
  775. var d = GridBroadphase_collisionPairs_d;
  776. d.set(xreset, yreset, zreset);
  777. for (var xi = 0, xoff = 0; xi !== nx; xi++, xoff += xstep, d.y = yreset, d.x += binsizeX) {
  778. for (var yi = 0, yoff = 0; yi !== ny; yi++, yoff += ystep, d.z = zreset, d.y += binsizeY) {
  779. for (var zi = 0, zoff = 0; zi !== nz; zi++, zoff += zstep, d.z += binsizeZ) {
  780. if (d.dot(planeNormal) < binRadius) {
  781. var idx = xoff + yoff + zoff;
  782. bins[idx][binLengths[idx]++] = bi;
  783. }
  784. }
  785. }
  786. }
  787. break;
  788. default:
  789. if (bi.aabbNeedsUpdate) {
  790. bi.computeAABB();
  791. }
  792. addBoxToBins(
  793. bi.aabb.lowerBound.x,
  794. bi.aabb.lowerBound.y,
  795. bi.aabb.lowerBound.z,
  796. bi.aabb.upperBound.x,
  797. bi.aabb.upperBound.y,
  798. bi.aabb.upperBound.z,
  799. bi);
  800. break;
  801. }
  802. }
  803. // Check each bin
  804. for(var i=0; i!==Nbins; i++){
  805. var binLength = binLengths[i];
  806. //Skip bins with no potential collisions
  807. if (binLength > 1) {
  808. var bin = bins[i];
  809. // Do N^2 broadphase inside
  810. for(var xi=0; xi!==binLength; xi++){
  811. var bi = bin[xi];
  812. for(var yi=0; yi!==xi; yi++){
  813. var bj = bin[yi];
  814. if(this.needBroadphaseCollision(bi,bj)){
  815. this.intersectionTest(bi,bj,pairs1,pairs2);
  816. }
  817. }
  818. }
  819. }
  820. }
  821. // for (var zi = 0, zoff=0; zi < nz; zi++, zoff+= zstep) {
  822. // console.log("layer "+zi);
  823. // for (var yi = 0, yoff=0; yi < ny; yi++, yoff += ystep) {
  824. // var row = '';
  825. // for (var xi = 0, xoff=0; xi < nx; xi++, xoff += xstep) {
  826. // var idx = xoff + yoff + zoff;
  827. // row += ' ' + binLengths[idx];
  828. // }
  829. // console.log(row);
  830. // }
  831. // }
  832. this.makePairsUnique(pairs1,pairs2);
  833. };
  834. },{"../math/Vec3":30,"../shapes/Shape":43,"./Broadphase":5}],7:[function(_dereq_,module,exports){
  835. module.exports = NaiveBroadphase;
  836. var Broadphase = _dereq_('./Broadphase');
  837. var AABB = _dereq_('./AABB');
  838. /**
  839. * Naive broadphase implementation, used in lack of better ones.
  840. * @class NaiveBroadphase
  841. * @constructor
  842. * @description The naive broadphase looks at all possible pairs without restriction, therefore it has complexity N^2 (which is bad)
  843. * @extends Broadphase
  844. */
  845. function NaiveBroadphase(){
  846. Broadphase.apply(this);
  847. }
  848. NaiveBroadphase.prototype = new Broadphase();
  849. NaiveBroadphase.prototype.constructor = NaiveBroadphase;
  850. /**
  851. * Get all the collision pairs in the physics world
  852. * @method collisionPairs
  853. * @param {World} world
  854. * @param {Array} pairs1
  855. * @param {Array} pairs2
  856. */
  857. NaiveBroadphase.prototype.collisionPairs = function(world,pairs1,pairs2){
  858. var bodies = world.bodies,
  859. n = bodies.length,
  860. i,j,bi,bj;
  861. // Naive N^2 ftw!
  862. for(i=0; i!==n; i++){
  863. for(j=0; j!==i; j++){
  864. bi = bodies[i];
  865. bj = bodies[j];
  866. if(!this.needBroadphaseCollision(bi,bj)){
  867. continue;
  868. }
  869. this.intersectionTest(bi,bj,pairs1,pairs2);
  870. }
  871. }
  872. };
  873. var tmpAABB = new AABB();
  874. /**
  875. * Returns all the bodies within an AABB.
  876. * @method aabbQuery
  877. * @param {World} world
  878. * @param {AABB} aabb
  879. * @param {array} result An array to store resulting bodies in.
  880. * @return {array}
  881. */
  882. NaiveBroadphase.prototype.aabbQuery = function(world, aabb, result){
  883. result = result || [];
  884. for(var i = 0; i < world.bodies.length; i++){
  885. var b = world.bodies[i];
  886. if(b.aabbNeedsUpdate){
  887. b.computeAABB();
  888. }
  889. // Ugly hack until Body gets aabb
  890. if(b.aabb.overlaps(aabb)){
  891. result.push(b);
  892. }
  893. }
  894. return result;
  895. };
  896. },{"./AABB":3,"./Broadphase":5}],8:[function(_dereq_,module,exports){
  897. module.exports = ObjectCollisionMatrix;
  898. /**
  899. * Records what objects are colliding with each other
  900. * @class ObjectCollisionMatrix
  901. * @constructor
  902. */
  903. function ObjectCollisionMatrix() {
  904. /**
  905. * The matrix storage
  906. * @property matrix
  907. * @type {Object}
  908. */
  909. this.matrix = {};
  910. }
  911. /**
  912. * @method get
  913. * @param {Number} i
  914. * @param {Number} j
  915. * @return {Number}
  916. */
  917. ObjectCollisionMatrix.prototype.get = function(i, j) {
  918. i = i.id;
  919. j = j.id;
  920. if (j > i) {
  921. var temp = j;
  922. j = i;
  923. i = temp;
  924. }
  925. return i+'-'+j in this.matrix;
  926. };
  927. /**
  928. * @method set
  929. * @param {Number} i
  930. * @param {Number} j
  931. * @param {Number} value
  932. */
  933. ObjectCollisionMatrix.prototype.set = function(i, j, value) {
  934. i = i.id;
  935. j = j.id;
  936. if (j > i) {
  937. var temp = j;
  938. j = i;
  939. i = temp;
  940. }
  941. if (value) {
  942. this.matrix[i+'-'+j] = true;
  943. }
  944. else {
  945. delete this.matrix[i+'-'+j];
  946. }
  947. };
  948. /**
  949. * Empty the matrix
  950. * @method reset
  951. */
  952. ObjectCollisionMatrix.prototype.reset = function() {
  953. this.matrix = {};
  954. };
  955. /**
  956. * Set max number of objects
  957. * @method setNumObjects
  958. * @param {Number} n
  959. */
  960. ObjectCollisionMatrix.prototype.setNumObjects = function(n) {
  961. };
  962. },{}],9:[function(_dereq_,module,exports){
  963. module.exports = Ray;
  964. var Vec3 = _dereq_('../math/Vec3');
  965. var Quaternion = _dereq_('../math/Quaternion');
  966. var Transform = _dereq_('../math/Transform');
  967. var ConvexPolyhedron = _dereq_('../shapes/ConvexPolyhedron');
  968. var Box = _dereq_('../shapes/Box');
  969. var RaycastResult = _dereq_('../collision/RaycastResult');
  970. var Shape = _dereq_('../shapes/Shape');
  971. var AABB = _dereq_('../collision/AABB');
  972. /**
  973. * A line in 3D space that intersects bodies and return points.
  974. * @class Ray
  975. * @constructor
  976. * @param {Vec3} from
  977. * @param {Vec3} to
  978. */
  979. function Ray(from, to){
  980. /**
  981. * @property {Vec3} from
  982. */
  983. this.from = from ? from.clone() : new Vec3();
  984. /**
  985. * @property {Vec3} to
  986. */
  987. this.to = to ? to.clone() : new Vec3();
  988. /**
  989. * @private
  990. * @property {Vec3} _direction
  991. */
  992. this._direction = new Vec3();
  993. /**
  994. * The precision of the ray. Used when checking parallelity etc.
  995. * @property {Number} precision
  996. */
  997. this.precision = 0.0001;
  998. /**
  999. * Set to true if you want the Ray to take .collisionResponse flags into account on bodies and shapes.
  1000. * @property {Boolean} checkCollisionResponse
  1001. */
  1002. this.checkCollisionResponse = true;
  1003. /**
  1004. * If set to true, the ray skips any hits with normal.dot(rayDirection) < 0.
  1005. * @property {Boolean} skipBackfaces
  1006. */
  1007. this.skipBackfaces = false;
  1008. /**
  1009. * @property {number} collisionFilterMask
  1010. * @default -1
  1011. */
  1012. this.collisionFilterMask = -1;
  1013. /**
  1014. * @property {number} collisionFilterGroup
  1015. * @default -1
  1016. */
  1017. this.collisionFilterGroup = -1;
  1018. /**
  1019. * The intersection mode. Should be Ray.ANY, Ray.ALL or Ray.CLOSEST.
  1020. * @property {number} mode
  1021. */
  1022. this.mode = Ray.ANY;
  1023. /**
  1024. * Current result object.
  1025. * @property {RaycastResult} result
  1026. */
  1027. this.result = new RaycastResult();
  1028. /**
  1029. * Will be set to true during intersectWorld() if the ray hit anything.
  1030. * @property {Boolean} hasHit
  1031. */
  1032. this.hasHit = false;
  1033. /**
  1034. * Current, user-provided result callback. Will be used if mode is Ray.ALL.
  1035. * @property {Function} callback
  1036. */
  1037. this.callback = function(result){};
  1038. }
  1039. Ray.prototype.constructor = Ray;
  1040. Ray.CLOSEST = 1;
  1041. Ray.ANY = 2;
  1042. Ray.ALL = 4;
  1043. var tmpAABB = new AABB();
  1044. var tmpArray = [];
  1045. /**
  1046. * Do itersection against all bodies in the given World.
  1047. * @method intersectWorld
  1048. * @param {World} world
  1049. * @param {object} options
  1050. * @return {Boolean} True if the ray hit anything, otherwise false.
  1051. */
  1052. Ray.prototype.intersectWorld = function (world, options) {
  1053. this.mode = options.mode || Ray.ANY;
  1054. this.result = options.result || new RaycastResult();
  1055. this.skipBackfaces = !!options.skipBackfaces;
  1056. this.collisionFilterMask = typeof(options.collisionFilterMask) !== 'undefined' ? options.collisionFilterMask : -1;
  1057. this.collisionFilterGroup = typeof(options.collisionFilterGroup) !== 'undefined' ? options.collisionFilterGroup : -1;
  1058. if(options.from){
  1059. this.from.copy(options.from);
  1060. }
  1061. if(options.to){
  1062. this.to.copy(options.to);
  1063. }
  1064. this.callback = options.callback || function(){};
  1065. this.hasHit = false;
  1066. this.result.reset();
  1067. this._updateDirection();
  1068. this.getAABB(tmpAABB);
  1069. tmpArray.length = 0;
  1070. world.broadphase.aabbQuery(world, tmpAABB, tmpArray);
  1071. this.intersectBodies(tmpArray);
  1072. return this.hasHit;
  1073. };
  1074. var v1 = new Vec3(),
  1075. v2 = new Vec3();
  1076. /*
  1077. * As per "Barycentric Technique" as named here http://www.blackpawn.com/texts/pointinpoly/default.html But without the division
  1078. */
  1079. Ray.pointInTriangle = pointInTriangle;
  1080. function pointInTriangle(p, a, b, c) {
  1081. c.vsub(a,v0);
  1082. b.vsub(a,v1);
  1083. p.vsub(a,v2);
  1084. var dot00 = v0.dot( v0 );
  1085. var dot01 = v0.dot( v1 );
  1086. var dot02 = v0.dot( v2 );
  1087. var dot11 = v1.dot( v1 );
  1088. var dot12 = v1.dot( v2 );
  1089. var u,v;
  1090. return ( (u = dot11 * dot02 - dot01 * dot12) >= 0 ) &&
  1091. ( (v = dot00 * dot12 - dot01 * dot02) >= 0 ) &&
  1092. ( u + v < ( dot00 * dot11 - dot01 * dot01 ) );
  1093. }
  1094. /**
  1095. * Shoot a ray at a body, get back information about the hit.
  1096. * @method intersectBody
  1097. * @private
  1098. * @param {Body} body
  1099. * @param {RaycastResult} [result] Deprecated - set the result property of the Ray instead.
  1100. */
  1101. var intersectBody_xi = new Vec3();
  1102. var intersectBody_qi = new Quaternion();
  1103. Ray.prototype.intersectBody = function (body, result) {
  1104. if(result){
  1105. this.result = result;
  1106. this._updateDirection();
  1107. }
  1108. var checkCollisionResponse = this.checkCollisionResponse;
  1109. if(checkCollisionResponse && !body.collisionResponse){
  1110. return;
  1111. }
  1112. if((this.collisionFilterGroup & body.collisionFilterMask)===0 || (body.collisionFilterGroup & this.collisionFilterMask)===0){
  1113. return;
  1114. }
  1115. var xi = intersectBody_xi;
  1116. var qi = intersectBody_qi;
  1117. for (var i = 0, N = body.shapes.length; i < N; i++) {
  1118. var shape = body.shapes[i];
  1119. if(checkCollisionResponse && !shape.collisionResponse){
  1120. continue; // Skip
  1121. }
  1122. body.quaternion.mult(body.shapeOrientations[i], qi);
  1123. body.quaternion.vmult(body.shapeOffsets[i], xi);
  1124. xi.vadd(body.position, xi);
  1125. this.intersectShape(
  1126. shape,
  1127. qi,
  1128. xi,
  1129. body
  1130. );
  1131. if(this.result._shouldStop){
  1132. break;
  1133. }
  1134. }
  1135. };
  1136. /**
  1137. * @method intersectBodies
  1138. * @param {Array} bodies An array of Body objects.
  1139. * @param {RaycastResult} [result] Deprecated
  1140. */
  1141. Ray.prototype.intersectBodies = function (bodies, result) {
  1142. if(result){
  1143. this.result = result;
  1144. this._updateDirection();
  1145. }
  1146. for ( var i = 0, l = bodies.length; !this.result._shouldStop && i < l; i ++ ) {
  1147. this.intersectBody(bodies[i]);
  1148. }
  1149. };
  1150. /**
  1151. * Updates the _direction vector.
  1152. * @private
  1153. * @method _updateDirection
  1154. */
  1155. Ray.prototype._updateDirection = function(){
  1156. this.to.vsub(this.from, this._direction);
  1157. this._direction.normalize();
  1158. };
  1159. /**
  1160. * @method intersectShape
  1161. * @private
  1162. * @param {Shape} shape
  1163. * @param {Quaternion} quat
  1164. * @param {Vec3} position
  1165. * @param {Body} body
  1166. */
  1167. Ray.prototype.intersectShape = function(shape, quat, position, body){
  1168. var from = this.from;
  1169. // Checking boundingSphere
  1170. var distance = distanceFromIntersection(from, this._direction, position);
  1171. if ( distance > shape.boundingSphereRadius ) {
  1172. return;
  1173. }
  1174. var intersectMethod = this[shape.type];
  1175. if(intersectMethod){
  1176. intersectMethod.call(this, shape, quat, position, body);
  1177. }
  1178. };
  1179. var vector = new Vec3();
  1180. var normal = new Vec3();
  1181. var intersectPoint = new Vec3();
  1182. var a = new Vec3();
  1183. var b = new Vec3();
  1184. var c = new Vec3();
  1185. var d = new Vec3();
  1186. var tmpRaycastResult = new RaycastResult();
  1187. /**
  1188. * @method intersectBox
  1189. * @private
  1190. * @param {Shape} shape
  1191. * @param {Quaternion} quat
  1192. * @param {Vec3} position
  1193. * @param {Body} body
  1194. */
  1195. Ray.prototype.intersectBox = function(shape, quat, position, body){
  1196. return this.intersectConvex(shape.convexPolyhedronRepresentation, quat, position, body);
  1197. };
  1198. Ray.prototype[Shape.types.BOX] = Ray.prototype.intersectBox;
  1199. /**
  1200. * @method intersectPlane
  1201. * @private
  1202. * @param {Shape} shape
  1203. * @param {Quaternion} quat
  1204. * @param {Vec3} position
  1205. * @param {Body} body
  1206. */
  1207. Ray.prototype.intersectPlane = function(shape, quat, position, body){
  1208. var from = this.from;
  1209. var to = this.to;
  1210. var direction = this._direction;
  1211. // Get plane normal
  1212. var worldNormal = new Vec3(0, 0, 1);
  1213. quat.vmult(worldNormal, worldNormal);
  1214. var len = new Vec3();
  1215. from.vsub(position, len);
  1216. var planeToFrom = len.dot(worldNormal);
  1217. to.vsub(position, len);
  1218. var planeToTo = len.dot(worldNormal);
  1219. if(planeToFrom * planeToTo > 0){
  1220. // "from" and "to" are on the same side of the plane... bail out
  1221. return;
  1222. }
  1223. if(from.distanceTo(to) < planeToFrom){
  1224. return;
  1225. }
  1226. var n_dot_dir = worldNormal.dot(direction);
  1227. if (Math.abs(n_dot_dir) < this.precision) {
  1228. // No intersection
  1229. return;
  1230. }
  1231. var planePointToFrom = new Vec3();
  1232. var dir_scaled_with_t = new Vec3();
  1233. var hitPointWorld = new Vec3();
  1234. from.vsub(position, planePointToFrom);
  1235. var t = -worldNormal.dot(planePointToFrom) / n_dot_dir;
  1236. direction.scale(t, dir_scaled_with_t);
  1237. from.vadd(dir_scaled_with_t, hitPointWorld);
  1238. this.reportIntersection(worldNormal, hitPointWorld, shape, body, -1);
  1239. };
  1240. Ray.prototype[Shape.types.PLANE] = Ray.prototype.intersectPlane;
  1241. /**
  1242. * Get the world AABB of the ray.
  1243. * @method getAABB
  1244. * @param {AABB} aabb
  1245. */
  1246. Ray.prototype.getAABB = function(result){
  1247. var to = this.to;
  1248. var from = this.from;
  1249. result.lowerBound.x = Math.min(to.x, from.x);
  1250. result.lowerBound.y = Math.min(to.y, from.y);
  1251. result.lowerBound.z = Math.min(to.z, from.z);
  1252. result.upperBound.x = Math.max(to.x, from.x);
  1253. result.upperBound.y = Math.max(to.y, from.y);
  1254. result.upperBound.z = Math.max(to.z, from.z);
  1255. };
  1256. var intersectConvexOptions = {
  1257. faceList: [0]
  1258. };
  1259. /**
  1260. * @method intersectHeightfield
  1261. * @private
  1262. * @param {Shape} shape
  1263. * @param {Quaternion} quat
  1264. * @param {Vec3} position
  1265. * @param {Body} body
  1266. */
  1267. Ray.prototype.intersectHeightfield = function(shape, quat, position, body){
  1268. var data = shape.data,
  1269. w = shape.elementSize,
  1270. worldPillarOffset = new Vec3();
  1271. // Convert the ray to local heightfield coordinates
  1272. var localRay = new Ray(this.from, this.to);
  1273. Transform.pointToLocalFrame(position, quat, localRay.from, localRay.from);
  1274. Transform.pointToLocalFrame(position, quat, localRay.to, localRay.to);
  1275. // Get the index of the data points to test against
  1276. var index = [];
  1277. var iMinX = null;
  1278. var iMinY = null;
  1279. var iMaxX = null;
  1280. var iMaxY = null;
  1281. var inside = shape.getIndexOfPosition(localRay.from.x, localRay.from.y, index, false);
  1282. if(inside){
  1283. iMinX = index[0];
  1284. iMinY = index[1];
  1285. iMaxX = index[0];
  1286. iMaxY = index[1];
  1287. }
  1288. inside = shape.getIndexOfPosition(localRay.to.x, localRay.to.y, index, false);
  1289. if(inside){
  1290. if (iMinX === null || index[0] < iMinX) { iMinX = index[0]; }
  1291. if (iMaxX === null || index[0] > iMaxX) { iMaxX = index[0]; }
  1292. if (iMinY === null || index[1] < iMinY) { iMinY = index[1]; }
  1293. if (iMaxY === null || index[1] > iMaxY) { iMaxY = index[1]; }
  1294. }
  1295. if(iMinX === null){
  1296. return;
  1297. }
  1298. var minMax = [];
  1299. shape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
  1300. var min = minMax[0];
  1301. var max = minMax[1];
  1302. // // Bail out if the ray can't touch the bounding box
  1303. // // TODO
  1304. // var aabb = new AABB();
  1305. // this.getAABB(aabb);
  1306. // if(aabb.intersects()){
  1307. // return;
  1308. // }
  1309. for(var i = iMinX; i <= iMaxX; i++){
  1310. for(var j = iMinY; j <= iMaxY; j++){
  1311. if(this.result._shouldStop){
  1312. return;
  1313. }
  1314. // Lower triangle
  1315. shape.getConvexTrianglePillar(i, j, false);
  1316. Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
  1317. this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, intersectConvexOptions);
  1318. if(this.result._shouldStop){
  1319. return;
  1320. }
  1321. // Upper triangle
  1322. shape.getConvexTrianglePillar(i, j, true);
  1323. Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
  1324. this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, intersectConvexOptions);
  1325. }
  1326. }
  1327. };
  1328. Ray.prototype[Shape.types.HEIGHTFIELD] = Ray.prototype.intersectHeightfield;
  1329. var Ray_intersectSphere_intersectionPoint = new Vec3();
  1330. var Ray_intersectSphere_normal = new Vec3();
  1331. /**
  1332. * @method intersectSphere
  1333. * @private
  1334. * @param {Shape} shape
  1335. * @param {Quaternion} quat
  1336. * @param {Vec3} position
  1337. * @param {Body} body
  1338. */
  1339. Ray.prototype.intersectSphere = function(shape, quat, position, body){
  1340. var from = this.from,
  1341. to = this.to,
  1342. r = shape.radius;
  1343. var a = Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2) + Math.pow(to.z - from.z, 2);
  1344. var b = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z));
  1345. var c = Math.pow(from.x - position.x, 2) + Math.pow(from.y - position.y, 2) + Math.pow(from.z - position.z, 2) - Math.pow(r, 2);
  1346. var delta = Math.pow(b, 2) - 4 * a * c;
  1347. var intersectionPoint = Ray_intersectSphere_intersectionPoint;
  1348. var normal = Ray_intersectSphere_normal;
  1349. if(delta < 0){
  1350. // No intersection
  1351. return;
  1352. } else if(delta === 0){
  1353. // single intersection point
  1354. from.lerp(to, delta, intersectionPoint);
  1355. intersectionPoint.vsub(position, normal);
  1356. normal.normalize();
  1357. this.reportIntersection(normal, intersectionPoint, shape, body, -1);
  1358. } else {
  1359. var d1 = (- b - Math.sqrt(delta)) / (2 * a);
  1360. var d2 = (- b + Math.sqrt(delta)) / (2 * a);
  1361. if(d1 >= 0 && d1 <= 1){
  1362. from.lerp(to, d1, intersectionPoint);
  1363. intersectionPoint.vsub(position, normal);
  1364. normal.normalize();
  1365. this.reportIntersection(normal, intersectionPoint, shape, body, -1);
  1366. }
  1367. if(this.result._shouldStop){
  1368. return;
  1369. }
  1370. if(d2 >= 0 && d2 <= 1){
  1371. from.lerp(to, d2, intersectionPoint);
  1372. intersectionPoint.vsub(position, normal);
  1373. normal.normalize();
  1374. this.reportIntersection(normal, intersectionPoint, shape, body, -1);
  1375. }
  1376. }
  1377. };
  1378. Ray.prototype[Shape.types.SPHERE] = Ray.prototype.intersectSphere;
  1379. var intersectConvex_normal = new Vec3();
  1380. var intersectConvex_minDistNormal = new Vec3();
  1381. var intersectConvex_minDistIntersect = new Vec3();
  1382. var intersectConvex_vector = new Vec3();
  1383. /**
  1384. * @method intersectConvex
  1385. * @private
  1386. * @param {Shape} shape
  1387. * @param {Quaternion} quat
  1388. * @param {Vec3} position
  1389. * @param {Body} body
  1390. * @param {object} [options]
  1391. * @param {array} [options.faceList]
  1392. */
  1393. Ray.prototype.intersectConvex = function intersectConvex(
  1394. shape,
  1395. quat,
  1396. position,
  1397. body,
  1398. options
  1399. ){
  1400. var minDistNormal = intersectConvex_minDistNormal;
  1401. var normal = intersectConvex_normal;
  1402. var vector = intersectConvex_vector;
  1403. var minDistIntersect = intersectConvex_minDistIntersect;
  1404. var faceList = (options && options.faceList) || null;
  1405. // Checking faces
  1406. var faces = shape.faces,
  1407. vertices = shape.vertices,
  1408. normals = shape.faceNormals;
  1409. var direction = this._direction;
  1410. var from = this.from;
  1411. var to = this.to;
  1412. var fromToDistance = from.distanceTo(to);
  1413. var minDist = -1;
  1414. var Nfaces = faceList ? faceList.length : faces.length;
  1415. var result = this.result;
  1416. for (var j = 0; !result._shouldStop && j < Nfaces; j++) {
  1417. var fi = faceList ? faceList[j] : j;
  1418. var face = faces[fi];
  1419. var faceNormal = normals[fi];
  1420. var q = quat;
  1421. var x = position;
  1422. // determine if ray intersects the plane of the face
  1423. // note: this works regardless of the direction of the face normal
  1424. // Get plane point in world coordinates...
  1425. vector.copy(vertices[face[0]]);
  1426. q.vmult(vector,vector);
  1427. vector.vadd(x,vector);
  1428. // ...but make it relative to the ray from. We'll fix this later.
  1429. vector.vsub(from,vector);
  1430. // Get plane normal
  1431. q.vmult(faceNormal,normal);
  1432. // If this dot product is negative, we have something interesting
  1433. var dot = direction.dot(normal);
  1434. // Bail out if ray and plane are parallel
  1435. if ( Math.abs( dot ) < this.precision ){
  1436. continue;
  1437. }
  1438. // calc distance to plane
  1439. var scalar = normal.dot(vector) / dot;
  1440. // if negative distance, then plane is behind ray
  1441. if (scalar < 0){
  1442. continue;
  1443. }
  1444. // if (dot < 0) {
  1445. // Intersection point is from + direction * scalar
  1446. direction.mult(scalar,intersectPoint);
  1447. intersectPoint.vadd(from,intersectPoint);
  1448. // a is the point we compare points b and c with.
  1449. a.copy(vertices[face[0]]);
  1450. q.vmult(a,a);
  1451. x.vadd(a,a);
  1452. for(var i = 1; !result._shouldStop && i < face.length - 1; i++){
  1453. // Transform 3 vertices to world coords
  1454. b.copy(vertices[face[i]]);
  1455. c.copy(vertices[face[i+1]]);
  1456. q.vmult(b,b);
  1457. q.vmult(c,c);
  1458. x.vadd(b,b);
  1459. x.vadd(c,c);
  1460. var distance = intersectPoint.distanceTo(from);
  1461. if(!(pointInTriangle(intersectPoint, a, b, c) || pointInTriangle(intersectPoint, b, a, c)) || distance > fromToDistance){
  1462. continue;
  1463. }
  1464. this.reportIntersection(normal, intersectPoint, shape, body, fi);
  1465. }
  1466. // }
  1467. }
  1468. };
  1469. Ray.prototype[Shape.types.CONVEXPOLYHEDRON] = Ray.prototype.intersectConvex;
  1470. var intersectTrimesh_normal = new Vec3();
  1471. var intersectTrimesh_localDirection = new Vec3();
  1472. var intersectTrimesh_localFrom = new Vec3();
  1473. var intersectTrimesh_localTo = new Vec3();
  1474. var intersectTrimesh_worldNormal = new Vec3();
  1475. var intersectTrimesh_worldIntersectPoint = new Vec3();
  1476. var intersectTrimesh_localAABB = new AABB();
  1477. var intersectTrimesh_triangles = [];
  1478. var intersectTrimesh_treeTransform = new Transform();
  1479. /**
  1480. * @method intersectTrimesh
  1481. * @private
  1482. * @param {Shape} shape
  1483. * @param {Quaternion} quat
  1484. * @param {Vec3} position
  1485. * @param {Body} body
  1486. * @param {object} [options]
  1487. * @todo Optimize by transforming the world to local space first.
  1488. * @todo Use Octree lookup
  1489. */
  1490. Ray.prototype.intersectTrimesh = function intersectTrimesh(
  1491. mesh,
  1492. quat,
  1493. position,
  1494. body,
  1495. options
  1496. ){
  1497. var normal = intersectTrimesh_normal;
  1498. var triangles = intersectTrimesh_triangles;
  1499. var treeTransform = intersectTrimesh_treeTransform;
  1500. var minDistNormal = intersectConvex_minDistNormal;
  1501. var vector = intersectConvex_vector;
  1502. var minDistIntersect = intersectConvex_minDistIntersect;
  1503. var localAABB = intersectTrimesh_localAABB;
  1504. var localDirection = intersectTrimesh_localDirection;
  1505. var localFrom = intersectTrimesh_localFrom;
  1506. var localTo = intersectTrimesh_localTo;
  1507. var worldIntersectPoint = intersectTrimesh_worldIntersectPoint;
  1508. var worldNormal = intersectTrimesh_worldNormal;
  1509. var faceList = (options && options.faceList) || null;
  1510. // Checking faces
  1511. var indices = mesh.indices,
  1512. vertices = mesh.vertices,
  1513. normals = mesh.faceNormals;
  1514. var from = this.from;
  1515. var to = this.to;
  1516. var direction = this._direction;
  1517. var minDist = -1;
  1518. treeTransform.position.copy(position);
  1519. treeTransform.quaternion.copy(quat);
  1520. // Transform ray to local space!
  1521. Transform.vectorToLocalFrame(position, quat, direction, localDirection);
  1522. //body.vectorToLocalFrame(direction, localDirection);
  1523. Transform.pointToLocalFrame(position, quat, from, localFrom);
  1524. //body.pointToLocalFrame(from, localFrom);
  1525. Transform.pointToLocalFrame(position, quat, to, localTo);
  1526. //body.pointToLocalFrame(to, localTo);
  1527. var fromToDistanceSquared = localFrom.distanceSquared(localTo);
  1528. mesh.tree.rayQuery(this, treeTransform, triangles);
  1529. for (var i = 0, N = triangles.length; !this.result._shouldStop && i !== N; i++) {
  1530. var trianglesIndex = triangles[i];
  1531. mesh.getNormal(trianglesIndex, normal);
  1532. // determine if ray intersects the plane of the face
  1533. // note: this works regardless of the direction of the face normal
  1534. // Get plane point in world coordinates...
  1535. mesh.getVertex(indices[trianglesIndex * 3], a);
  1536. // ...but make it relative to the ray from. We'll fix this later.
  1537. a.vsub(localFrom,vector);
  1538. // Get plane normal
  1539. // quat.vmult(normal, normal);
  1540. // If this dot product is negative, we have something interesting
  1541. var dot = localDirection.dot(normal);
  1542. // Bail out if ray and plane are parallel
  1543. // if (Math.abs( dot ) < this.precision){
  1544. // continue;
  1545. // }
  1546. // calc distance to plane
  1547. var scalar = normal.dot(vector) / dot;
  1548. // if negative distance, then plane is behind ray
  1549. if (scalar < 0){
  1550. continue;
  1551. }
  1552. // Intersection point is from + direction * scalar
  1553. localDirection.scale(scalar,intersectPoint);
  1554. intersectPoint.vadd(localFrom,intersectPoint);
  1555. // Get triangle vertices
  1556. mesh.getVertex(indices[trianglesIndex * 3 + 1], b);
  1557. mesh.getVertex(indices[trianglesIndex * 3 + 2], c);
  1558. var squaredDistance = intersectPoint.distanceSquared(localFrom);
  1559. if(!(pointInTriangle(intersectPoint, b, a, c) || pointInTriangle(intersectPoint, a, b, c)) || squaredDistance > fromToDistanceSquared){
  1560. continue;
  1561. }
  1562. // transform intersectpoint and normal to world
  1563. Transform.vectorToWorldFrame(quat, normal, worldNormal);
  1564. //body.vectorToWorldFrame(normal, worldNormal);
  1565. Transform.pointToWorldFrame(position, quat, intersectPoint, worldIntersectPoint);
  1566. //body.pointToWorldFrame(intersectPoint, worldIntersectPoint);
  1567. this.reportIntersection(worldNormal, worldIntersectPoint, mesh, body, trianglesIndex);
  1568. }
  1569. triangles.length = 0;
  1570. };
  1571. Ray.prototype[Shape.types.TRIMESH] = Ray.prototype.intersectTrimesh;
  1572. /**
  1573. * @method reportIntersection
  1574. * @private
  1575. * @param {Vec3} normal
  1576. * @param {Vec3} hitPointWorld
  1577. * @param {Shape} shape
  1578. * @param {Body} body
  1579. * @return {boolean} True if the intersections should continue
  1580. */
  1581. Ray.prototype.reportIntersection = function(normal, hitPointWorld, shape, body, hitFaceIndex){
  1582. var from = this.from;
  1583. var to = this.to;
  1584. var distance = from.distanceTo(hitPointWorld);
  1585. var result = this.result;
  1586. // Skip back faces?
  1587. if(this.skipBackfaces && normal.dot(this._direction) > 0){
  1588. return;
  1589. }
  1590. result.hitFaceIndex = typeof(hitFaceIndex) !== 'undefined' ? hitFaceIndex : -1;
  1591. switch(this.mode){
  1592. case Ray.ALL:
  1593. this.hasHit = true;
  1594. result.set(
  1595. from,
  1596. to,
  1597. normal,
  1598. hitPointWorld,
  1599. shape,
  1600. body,
  1601. distance
  1602. );
  1603. result.hasHit = true;
  1604. this.callback(result);
  1605. break;
  1606. case Ray.CLOSEST:
  1607. // Store if closer than current closest
  1608. if(distance < result.distance || !result.hasHit){
  1609. this.hasHit = true;
  1610. result.hasHit = true;
  1611. result.set(
  1612. from,
  1613. to,
  1614. normal,
  1615. hitPointWorld,
  1616. shape,
  1617. body,
  1618. distance
  1619. );
  1620. }
  1621. break;
  1622. case Ray.ANY:
  1623. // Report and stop.
  1624. this.hasHit = true;
  1625. result.hasHit = true;
  1626. result.set(
  1627. from,
  1628. to,
  1629. normal,
  1630. hitPointWorld,
  1631. shape,
  1632. body,
  1633. distance
  1634. );
  1635. result._shouldStop = true;
  1636. break;
  1637. }
  1638. };
  1639. var v0 = new Vec3(),
  1640. intersect = new Vec3();
  1641. function distanceFromIntersection(from, direction, position) {
  1642. // v0 is vector from from to position
  1643. position.vsub(from,v0);
  1644. var dot = v0.dot(direction);
  1645. // intersect = direction*dot + from
  1646. direction.mult(dot,intersect);
  1647. intersect.vadd(from,intersect);
  1648. var distance = position.distanceTo(intersect);
  1649. return distance;
  1650. }
  1651. },{"../collision/AABB":3,"../collision/RaycastResult":10,"../math/Quaternion":28,"../math/Transform":29,"../math/Vec3":30,"../shapes/Box":37,"../shapes/ConvexPolyhedron":38,"../shapes/Shape":43}],10:[function(_dereq_,module,exports){
  1652. var Vec3 = _dereq_('../math/Vec3');
  1653. module.exports = RaycastResult;
  1654. /**
  1655. * Storage for Ray casting data.
  1656. * @class RaycastResult
  1657. * @constructor
  1658. */
  1659. function RaycastResult(){
  1660. /**
  1661. * @property {Vec3} rayFromWorld
  1662. */
  1663. this.rayFromWorld = new Vec3();
  1664. /**
  1665. * @property {Vec3} rayToWorld
  1666. */
  1667. this.rayToWorld = new Vec3();
  1668. /**
  1669. * @property {Vec3} hitNormalWorld
  1670. */
  1671. this.hitNormalWorld = new Vec3();
  1672. /**
  1673. * @property {Vec3} hitPointWorld
  1674. */
  1675. this.hitPointWorld = new Vec3();
  1676. /**
  1677. * @property {boolean} hasHit
  1678. */
  1679. this.hasHit = false;
  1680. /**
  1681. * The hit shape, or null.
  1682. * @property {Shape} shape
  1683. */
  1684. this.shape = null;
  1685. /**
  1686. * The hit body, or null.
  1687. * @property {Body} body
  1688. */
  1689. this.body = null;
  1690. /**
  1691. * The index of the hit triangle, if the hit shape was a trimesh.
  1692. * @property {number} hitFaceIndex
  1693. * @default -1
  1694. */
  1695. this.hitFaceIndex = -1;
  1696. /**
  1697. * Distance to the hit. Will be set to -1 if there was no hit.
  1698. * @property {number} distance
  1699. * @default -1
  1700. */
  1701. this.distance = -1;
  1702. /**
  1703. * If the ray should stop traversing the bodies.
  1704. * @private
  1705. * @property {Boolean} _shouldStop
  1706. * @default false
  1707. */
  1708. this._shouldStop = false;
  1709. }
  1710. /**
  1711. * Reset all result data.
  1712. * @method reset
  1713. */
  1714. RaycastResult.prototype.reset = function () {
  1715. this.rayFromWorld.setZero();
  1716. this.rayToWorld.setZero();
  1717. this.hitNormalWorld.setZero();
  1718. this.hitPointWorld.setZero();
  1719. this.hasHit = false;
  1720. this.shape = null;
  1721. this.body = null;
  1722. this.hitFaceIndex = -1;
  1723. this.distance = -1;
  1724. this._shouldStop = false;
  1725. };
  1726. /**
  1727. * @method abort
  1728. */
  1729. RaycastResult.prototype.abort = function(){
  1730. this._shouldStop = true;
  1731. };
  1732. /**
  1733. * @method set
  1734. * @param {Vec3} rayFromWorld
  1735. * @param {Vec3} rayToWorld
  1736. * @param {Vec3} hitNormalWorld
  1737. * @param {Vec3} hitPointWorld
  1738. * @param {Shape} shape
  1739. * @param {Body} body
  1740. * @param {number} distance
  1741. */
  1742. RaycastResult.prototype.set = function(
  1743. rayFromWorld,
  1744. rayToWorld,
  1745. hitNormalWorld,
  1746. hitPointWorld,
  1747. shape,
  1748. body,
  1749. distance
  1750. ){
  1751. this.rayFromWorld.copy(rayFromWorld);
  1752. this.rayToWorld.copy(rayToWorld);
  1753. this.hitNormalWorld.copy(hitNormalWorld);
  1754. this.hitPointWorld.copy(hitPointWorld);
  1755. this.shape = shape;
  1756. this.body = body;
  1757. this.distance = distance;
  1758. };
  1759. },{"../math/Vec3":30}],11:[function(_dereq_,module,exports){
  1760. var Shape = _dereq_('../shapes/Shape');
  1761. var Broadphase = _dereq_('../collision/Broadphase');
  1762. module.exports = SAPBroadphase;
  1763. /**
  1764. * Sweep and prune broadphase along one axis.
  1765. *
  1766. * @class SAPBroadphase
  1767. * @constructor
  1768. * @param {World} [world]
  1769. * @extends Broadphase
  1770. */
  1771. function SAPBroadphase(world){
  1772. Broadphase.apply(this);
  1773. /**
  1774. * List of bodies currently in the broadphase.
  1775. * @property axisList
  1776. * @type {Array}
  1777. */
  1778. this.axisList = [];
  1779. /**
  1780. * The world to search in.
  1781. * @property world
  1782. * @type {World}
  1783. */
  1784. this.world = null;
  1785. /**
  1786. * Axis to sort the bodies along. Set to 0 for x axis, and 1 for y axis. For best performance, choose an axis that the bodies are spread out more on.
  1787. * @property axisIndex
  1788. * @type {Number}
  1789. */
  1790. this.axisIndex = 0;
  1791. var axisList = this.axisList;
  1792. this._addBodyHandler = function(e){
  1793. axisList.push(e.body);
  1794. };
  1795. this._removeBodyHandler = function(e){
  1796. var idx = axisList.indexOf(e.body);
  1797. if(idx !== -1){
  1798. axisList.splice(idx,1);
  1799. }
  1800. };
  1801. if(world){
  1802. this.setWorld(world);
  1803. }
  1804. }
  1805. SAPBroadphase.prototype = new Broadphase();
  1806. /**
  1807. * Change the world
  1808. * @method setWorld
  1809. * @param {World} world
  1810. */
  1811. SAPBroadphase.prototype.setWorld = function(world){
  1812. // Clear the old axis array
  1813. this.axisList.length = 0;
  1814. // Add all bodies from the new world
  1815. for(var i=0; i<world.bodies.length; i++){
  1816. this.axisList.push(world.bodies[i]);
  1817. }
  1818. // Remove old handlers, if any
  1819. world.removeEventListener("addBody", this._addBodyHandler);
  1820. world.removeEventListener("removeBody", this._removeBodyHandler);
  1821. // Add handlers to update the list of bodies.
  1822. world.addEventListener("addBody", this._addBodyHandler);
  1823. world.addEventListener("removeBody", this._removeBodyHandler);
  1824. this.world = world;
  1825. this.dirty = true;
  1826. };
  1827. /**
  1828. * @static
  1829. * @method insertionSortX
  1830. * @param {Array} a
  1831. * @return {Array}
  1832. */
  1833. SAPBroadphase.insertionSortX = function(a) {
  1834. for(var i=1,l=a.length;i<l;i++) {
  1835. var v = a[i];
  1836. for(var j=i - 1;j>=0;j--) {
  1837. if(a[j].aabb.lowerBound.x <= v.aabb.lowerBound.x){
  1838. break;
  1839. }
  1840. a[j+1] = a[j];
  1841. }
  1842. a[j+1] = v;
  1843. }
  1844. return a;
  1845. };
  1846. /**
  1847. * @static
  1848. * @method insertionSortY
  1849. * @param {Array} a
  1850. * @return {Array}
  1851. */
  1852. SAPBroadphase.insertionSortY = function(a) {
  1853. for(var i=1,l=a.length;i<l;i++) {
  1854. var v = a[i];
  1855. for(var j=i - 1;j>=0;j--) {
  1856. if(a[j].aabb.lowerBound.y <= v.aabb.lowerBound.y){
  1857. break;
  1858. }
  1859. a[j+1] = a[j];
  1860. }
  1861. a[j+1] = v;
  1862. }
  1863. return a;
  1864. };
  1865. /**
  1866. * @static
  1867. * @method insertionSortZ
  1868. * @param {Array} a
  1869. * @return {Array}
  1870. */
  1871. SAPBroadphase.insertionSortZ = function(a) {
  1872. for(var i=1,l=a.length;i<l;i++) {
  1873. var v = a[i];
  1874. for(var j=i - 1;j>=0;j--) {
  1875. if(a[j].aabb.lowerBound.z <= v.aabb.lowerBound.z){
  1876. break;
  1877. }
  1878. a[j+1] = a[j];
  1879. }
  1880. a[j+1] = v;
  1881. }
  1882. return a;
  1883. };
  1884. /**
  1885. * Collect all collision pairs
  1886. * @method collisionPairs
  1887. * @param {World} world
  1888. * @param {Array} p1
  1889. * @param {Array} p2
  1890. */
  1891. SAPBroadphase.prototype.collisionPairs = function(world,p1,p2){
  1892. var bodies = this.axisList,
  1893. N = bodies.length,
  1894. axisIndex = this.axisIndex,
  1895. i, j;
  1896. if(this.dirty){
  1897. this.sortList();
  1898. this.dirty = false;
  1899. }
  1900. // Look through the list
  1901. for(i=0; i !== N; i++){
  1902. var bi = bodies[i];
  1903. for(j=i+1; j < N; j++){
  1904. var bj = bodies[j];
  1905. if(!this.needBroadphaseCollision(bi,bj)){
  1906. continue;
  1907. }
  1908. if(!SAPBroadphase.checkBounds(bi,bj,axisIndex)){
  1909. break;
  1910. }
  1911. this.intersectionTest(bi,bj,p1,p2);
  1912. }
  1913. }
  1914. };
  1915. SAPBroadphase.prototype.sortList = function(){
  1916. var axisList = this.axisList;
  1917. var axisIndex = this.axisIndex;
  1918. var N = axisList.length;
  1919. // Update AABBs
  1920. for(var i = 0; i!==N; i++){
  1921. var bi = axisList[i];
  1922. if(bi.aabbNeedsUpdate){
  1923. bi.computeAABB();
  1924. }
  1925. }
  1926. // Sort the list
  1927. if(axisIndex === 0){
  1928. SAPBroadphase.insertionSortX(axisList);
  1929. } else if(axisIndex === 1){
  1930. SAPBroadphase.insertionSortY(axisList);
  1931. } else if(axisIndex === 2){
  1932. SAPBroadphase.insertionSortZ(axisList);
  1933. }
  1934. };
  1935. /**
  1936. * Check if the bounds of two bodies overlap, along the given SAP axis.
  1937. * @static
  1938. * @method checkBounds
  1939. * @param {Body} bi
  1940. * @param {Body} bj
  1941. * @param {Number} axisIndex
  1942. * @return {Boolean}
  1943. */
  1944. SAPBroadphase.checkBounds = function(bi, bj, axisIndex){
  1945. var biPos;
  1946. var bjPos;
  1947. if(axisIndex === 0){
  1948. biPos = bi.position.x;
  1949. bjPos = bj.position.x;
  1950. } else if(axisIndex === 1){
  1951. biPos = bi.position.y;
  1952. bjPos = bj.position.y;
  1953. } else if(axisIndex === 2){
  1954. biPos = bi.position.z;
  1955. bjPos = bj.position.z;
  1956. }
  1957. var ri = bi.boundingRadius,
  1958. rj = bj.boundingRadius,
  1959. boundA1 = biPos - ri,
  1960. boundA2 = biPos + ri,
  1961. boundB1 = bjPos - rj,
  1962. boundB2 = bjPos + rj;
  1963. return boundB1 < boundA2;
  1964. };
  1965. /**
  1966. * Computes the variance of the body positions and estimates the best
  1967. * axis to use. Will automatically set property .axisIndex.
  1968. * @method autoDetectAxis
  1969. */
  1970. SAPBroadphase.prototype.autoDetectAxis = function(){
  1971. var sumX=0,
  1972. sumX2=0,
  1973. sumY=0,
  1974. sumY2=0,
  1975. sumZ=0,
  1976. sumZ2=0,
  1977. bodies = this.axisList,
  1978. N = bodies.length,
  1979. invN=1/N;
  1980. for(var i=0; i!==N; i++){
  1981. var b = bodies[i];
  1982. var centerX = b.position.x;
  1983. sumX += centerX;
  1984. sumX2 += centerX*centerX;
  1985. var centerY = b.position.y;
  1986. sumY += centerY;
  1987. sumY2 += centerY*centerY;
  1988. var centerZ = b.position.z;
  1989. sumZ += centerZ;
  1990. sumZ2 += centerZ*centerZ;
  1991. }
  1992. var varianceX = sumX2 - sumX*sumX*invN,
  1993. varianceY = sumY2 - sumY*sumY*invN,
  1994. varianceZ = sumZ2 - sumZ*sumZ*invN;
  1995. if(varianceX > varianceY){
  1996. if(varianceX > varianceZ){
  1997. this.axisIndex = 0;
  1998. } else{
  1999. this.axisIndex = 2;
  2000. }
  2001. } else if(varianceY > varianceZ){
  2002. this.axisIndex = 1;
  2003. } else{
  2004. this.axisIndex = 2;
  2005. }
  2006. };
  2007. /**
  2008. * Returns all the bodies within an AABB.
  2009. * @method aabbQuery
  2010. * @param {World} world
  2011. * @param {AABB} aabb
  2012. * @param {array} result An array to store resulting bodies in.
  2013. * @return {array}
  2014. */
  2015. SAPBroadphase.prototype.aabbQuery = function(world, aabb, result){
  2016. result = result || [];
  2017. if(this.dirty){
  2018. this.sortList();
  2019. this.dirty = false;
  2020. }
  2021. var axisIndex = this.axisIndex, axis = 'x';
  2022. if(axisIndex === 1){ axis = 'y'; }
  2023. if(axisIndex === 2){ axis = 'z'; }
  2024. var axisList = this.axisList;
  2025. var lower = aabb.lowerBound[axis];
  2026. var upper = aabb.upperBound[axis];
  2027. for(var i = 0; i < axisList.length; i++){
  2028. var b = axisList[i];
  2029. if(b.aabbNeedsUpdate){
  2030. b.computeAABB();
  2031. }
  2032. if(b.aabb.overlaps(aabb)){
  2033. result.push(b);
  2034. }
  2035. }
  2036. return result;
  2037. };
  2038. },{"../collision/Broadphase":5,"../shapes/Shape":43}],12:[function(_dereq_,module,exports){
  2039. module.exports = ConeTwistConstraint;
  2040. var Constraint = _dereq_('./Constraint');
  2041. var PointToPointConstraint = _dereq_('./PointToPointConstraint');
  2042. var ConeEquation = _dereq_('../equations/ConeEquation');
  2043. var RotationalEquation = _dereq_('../equations/RotationalEquation');
  2044. var ContactEquation = _dereq_('../equations/ContactEquation');
  2045. var Vec3 = _dereq_('../math/Vec3');
  2046. /**
  2047. * @class ConeTwistConstraint
  2048. * @constructor
  2049. * @author schteppe
  2050. * @param {Body} bodyA
  2051. * @param {Body} bodyB
  2052. * @param {object} [options]
  2053. * @param {Vec3} [options.pivotA]
  2054. * @param {Vec3} [options.pivotB]
  2055. * @param {Vec3} [options.axisA]
  2056. * @param {Vec3} [options.axisB]
  2057. * @param {Number} [options.maxForce=1e6]
  2058. * @extends PointToPointConstraint
  2059. */
  2060. function ConeTwistConstraint(bodyA, bodyB, options){
  2061. options = options || {};
  2062. var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
  2063. // Set pivot point in between
  2064. var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
  2065. var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
  2066. this.axisA = options.axisA ? options.axisA.clone() : new Vec3();
  2067. this.axisB = options.axisB ? options.axisB.clone() : new Vec3();
  2068. PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
  2069. this.collideConnected = !!options.collideConnected;
  2070. this.angle = typeof(options.angle) !== 'undefined' ? options.angle : 0;
  2071. /**
  2072. * @property {ConeEquation} coneEquation
  2073. */
  2074. var c = this.coneEquation = new ConeEquation(bodyA,bodyB,options);
  2075. /**
  2076. * @property {RotationalEquation} twistEquation
  2077. */
  2078. var t = this.twistEquation = new RotationalEquation(bodyA,bodyB,options);
  2079. this.twistAngle = typeof(options.twistAngle) !== 'undefined' ? options.twistAngle : 0;
  2080. // Make the cone equation push the bodies toward the cone axis, not outward
  2081. c.maxForce = 0;
  2082. c.minForce = -maxForce;
  2083. // Make the twist equation add torque toward the initial position
  2084. t.maxForce = 0;
  2085. t.minForce = -maxForce;
  2086. this.equations.push(c, t);
  2087. }
  2088. ConeTwistConstraint.prototype = new PointToPointConstraint();
  2089. ConeTwistConstraint.constructor = ConeTwistConstraint;
  2090. var ConeTwistConstraint_update_tmpVec1 = new Vec3();
  2091. var ConeTwistConstraint_update_tmpVec2 = new Vec3();
  2092. ConeTwistConstraint.prototype.update = function(){
  2093. var bodyA = this.bodyA,
  2094. bodyB = this.bodyB,
  2095. cone = this.coneEquation,
  2096. twist = this.twistEquation;
  2097. PointToPointConstraint.prototype.update.call(this);
  2098. // Update the axes to the cone constraint
  2099. bodyA.vectorToWorldFrame(this.axisA, cone.axisA);
  2100. bodyB.vectorToWorldFrame(this.axisB, cone.axisB);
  2101. // Update the world axes in the twist constraint
  2102. this.axisA.tangents(twist.axisA, twist.axisA);
  2103. bodyA.vectorToWorldFrame(twist.axisA, twist.axisA);
  2104. this.axisB.tangents(twist.axisB, twist.axisB);
  2105. bodyB.vectorToWorldFrame(twist.axisB, twist.axisB);
  2106. cone.angle = this.angle;
  2107. twist.maxAngle = this.twistAngle;
  2108. };
  2109. },{"../equations/ConeEquation":18,"../equations/ContactEquation":19,"../equations/RotationalEquation":22,"../math/Vec3":30,"./Constraint":13,"./PointToPointConstraint":17}],13:[function(_dereq_,module,exports){
  2110. module.exports = Constraint;
  2111. var Utils = _dereq_('../utils/Utils');
  2112. /**
  2113. * Constraint base class
  2114. * @class Constraint
  2115. * @author schteppe
  2116. * @constructor
  2117. * @param {Body} bodyA
  2118. * @param {Body} bodyB
  2119. * @param {object} [options]
  2120. * @param {boolean} [options.collideConnected=true]
  2121. * @param {boolean} [options.wakeUpBodies=true]
  2122. */
  2123. function Constraint(bodyA, bodyB, options){
  2124. options = Utils.defaults(options,{
  2125. collideConnected : true,
  2126. wakeUpBodies : true,
  2127. });
  2128. /**
  2129. * Equations to be solved in this constraint
  2130. * @property equations
  2131. * @type {Array}
  2132. */
  2133. this.equations = [];
  2134. /**
  2135. * @property {Body} bodyA
  2136. */
  2137. this.bodyA = bodyA;
  2138. /**
  2139. * @property {Body} bodyB
  2140. */
  2141. this.bodyB = bodyB;
  2142. /**
  2143. * @property {Number} id
  2144. */
  2145. this.id = Constraint.idCounter++;
  2146. /**
  2147. * Set to true if you want the bodies to collide when they are connected.
  2148. * @property collideConnected
  2149. * @type {boolean}
  2150. */
  2151. this.collideConnected = options.collideConnected;
  2152. if(options.wakeUpBodies){
  2153. if(bodyA){
  2154. bodyA.wakeUp();
  2155. }
  2156. if(bodyB){
  2157. bodyB.wakeUp();
  2158. }
  2159. }
  2160. }
  2161. /**
  2162. * Update all the equations with data.
  2163. * @method update
  2164. */
  2165. Constraint.prototype.update = function(){
  2166. throw new Error("method update() not implmemented in this Constraint subclass!");
  2167. };
  2168. /**
  2169. * Enables all equations in the constraint.
  2170. * @method enable
  2171. */
  2172. Constraint.prototype.enable = function(){
  2173. var eqs = this.equations;
  2174. for(var i=0; i<eqs.length; i++){
  2175. eqs[i].enabled = true;
  2176. }
  2177. };
  2178. /**
  2179. * Disables all equations in the constraint.
  2180. * @method disable
  2181. */
  2182. Constraint.prototype.disable = function(){
  2183. var eqs = this.equations;
  2184. for(var i=0; i<eqs.length; i++){
  2185. eqs[i].enabled = false;
  2186. }
  2187. };
  2188. Constraint.idCounter = 0;
  2189. },{"../utils/Utils":53}],14:[function(_dereq_,module,exports){
  2190. module.exports = DistanceConstraint;
  2191. var Constraint = _dereq_('./Constraint');
  2192. var ContactEquation = _dereq_('../equations/ContactEquation');
  2193. /**
  2194. * Constrains two bodies to be at a constant distance from each others center of mass.
  2195. * @class DistanceConstraint
  2196. * @constructor
  2197. * @author schteppe
  2198. * @param {Body} bodyA
  2199. * @param {Body} bodyB
  2200. * @param {Number} [distance] The distance to keep. If undefined, it will be set to the current distance between bodyA and bodyB
  2201. * @param {Number} [maxForce=1e6]
  2202. * @extends Constraint
  2203. */
  2204. function DistanceConstraint(bodyA,bodyB,distance,maxForce){
  2205. Constraint.call(this,bodyA,bodyB);
  2206. if(typeof(distance)==="undefined") {
  2207. distance = bodyA.position.distanceTo(bodyB.position);
  2208. }
  2209. if(typeof(maxForce)==="undefined") {
  2210. maxForce = 1e6;
  2211. }
  2212. /**
  2213. * @property {number} distance
  2214. */
  2215. this.distance = distance;
  2216. /**
  2217. * @property {ContactEquation} distanceEquation
  2218. */
  2219. var eq = this.distanceEquation = new ContactEquation(bodyA, bodyB);
  2220. this.equations.push(eq);
  2221. // Make it bidirectional
  2222. eq.minForce = -maxForce;
  2223. eq.maxForce = maxForce;
  2224. }
  2225. DistanceConstraint.prototype = new Constraint();
  2226. DistanceConstraint.prototype.update = function(){
  2227. var bodyA = this.bodyA;
  2228. var bodyB = this.bodyB;
  2229. var eq = this.distanceEquation;
  2230. var halfDist = this.distance * 0.5;
  2231. var normal = eq.ni;
  2232. bodyB.position.vsub(bodyA.position, normal);
  2233. normal.normalize();
  2234. normal.mult(halfDist, eq.ri);
  2235. normal.mult(-halfDist, eq.rj);
  2236. };
  2237. },{"../equations/ContactEquation":19,"./Constraint":13}],15:[function(_dereq_,module,exports){
  2238. module.exports = HingeConstraint;
  2239. var Constraint = _dereq_('./Constraint');
  2240. var PointToPointConstraint = _dereq_('./PointToPointConstraint');
  2241. var RotationalEquation = _dereq_('../equations/RotationalEquation');
  2242. var RotationalMotorEquation = _dereq_('../equations/RotationalMotorEquation');
  2243. var ContactEquation = _dereq_('../equations/ContactEquation');
  2244. var Vec3 = _dereq_('../math/Vec3');
  2245. /**
  2246. * Hinge constraint. Think of it as a door hinge. It tries to keep the door in the correct place and with the correct orientation.
  2247. * @class HingeConstraint
  2248. * @constructor
  2249. * @author schteppe
  2250. * @param {Body} bodyA
  2251. * @param {Body} bodyB
  2252. * @param {object} [options]
  2253. * @param {Vec3} [options.pivotA] A point defined locally in bodyA. This defines the offset of axisA.
  2254. * @param {Vec3} [options.axisA] An axis that bodyA can rotate around, defined locally in bodyA.
  2255. * @param {Vec3} [options.pivotB]
  2256. * @param {Vec3} [options.axisB]
  2257. * @param {Number} [options.maxForce=1e6]
  2258. * @extends PointToPointConstraint
  2259. */
  2260. function HingeConstraint(bodyA, bodyB, options){
  2261. options = options || {};
  2262. var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
  2263. var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
  2264. var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
  2265. PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
  2266. /**
  2267. * Rotation axis, defined locally in bodyA.
  2268. * @property {Vec3} axisA
  2269. */
  2270. var axisA = this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1,0,0);
  2271. axisA.normalize();
  2272. /**
  2273. * Rotation axis, defined locally in bodyB.
  2274. * @property {Vec3} axisB
  2275. */
  2276. var axisB = this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1,0,0);
  2277. axisB.normalize();
  2278. /**
  2279. * @property {RotationalEquation} rotationalEquation1
  2280. */
  2281. var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA,bodyB,options);
  2282. /**
  2283. * @property {RotationalEquation} rotationalEquation2
  2284. */
  2285. var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA,bodyB,options);
  2286. /**
  2287. * @property {RotationalMotorEquation} motorEquation
  2288. */
  2289. var motor = this.motorEquation = new RotationalMotorEquation(bodyA,bodyB,maxForce);
  2290. motor.enabled = false; // Not enabled by default
  2291. // Equations to be fed to the solver
  2292. this.equations.push(
  2293. r1, // rotational1
  2294. r2, // rotational2
  2295. motor
  2296. );
  2297. }
  2298. HingeConstraint.prototype = new PointToPointConstraint();
  2299. HingeConstraint.constructor = HingeConstraint;
  2300. /**
  2301. * @method enableMotor
  2302. */
  2303. HingeConstraint.prototype.enableMotor = function(){
  2304. this.motorEquation.enabled = true;
  2305. };
  2306. /**
  2307. * @method disableMotor
  2308. */
  2309. HingeConstraint.prototype.disableMotor = function(){
  2310. this.motorEquation.enabled = false;
  2311. };
  2312. /**
  2313. * @method setMotorSpeed
  2314. * @param {number} speed
  2315. */
  2316. HingeConstraint.prototype.setMotorSpeed = function(speed){
  2317. this.motorEquation.targetVelocity = speed;
  2318. };
  2319. /**
  2320. * @method setMotorMaxForce
  2321. * @param {number} maxForce
  2322. */
  2323. HingeConstraint.prototype.setMotorMaxForce = function(maxForce){
  2324. this.motorEquation.maxForce = maxForce;
  2325. this.motorEquation.minForce = -maxForce;
  2326. };
  2327. var HingeConstraint_update_tmpVec1 = new Vec3();
  2328. var HingeConstraint_update_tmpVec2 = new Vec3();
  2329. HingeConstraint.prototype.update = function(){
  2330. var bodyA = this.bodyA,
  2331. bodyB = this.bodyB,
  2332. motor = this.motorEquation,
  2333. r1 = this.rotationalEquation1,
  2334. r2 = this.rotationalEquation2,
  2335. worldAxisA = HingeConstraint_update_tmpVec1,
  2336. worldAxisB = HingeConstraint_update_tmpVec2;
  2337. var axisA = this.axisA;
  2338. var axisB = this.axisB;
  2339. PointToPointConstraint.prototype.update.call(this);
  2340. // Get world axes
  2341. bodyA.quaternion.vmult(axisA, worldAxisA);
  2342. bodyB.quaternion.vmult(axisB, worldAxisB);
  2343. worldAxisA.tangents(r1.axisA, r2.axisA);
  2344. r1.axisB.copy(worldAxisB);
  2345. r2.axisB.copy(worldAxisB);
  2346. if(this.motorEquation.enabled){
  2347. bodyA.quaternion.vmult(this.axisA, motor.axisA);
  2348. bodyB.quaternion.vmult(this.axisB, motor.axisB);
  2349. }
  2350. };
  2351. },{"../equations/ContactEquation":19,"../equations/RotationalEquation":22,"../equations/RotationalMotorEquation":23,"../math/Vec3":30,"./Constraint":13,"./PointToPointConstraint":17}],16:[function(_dereq_,module,exports){
  2352. module.exports = LockConstraint;
  2353. var Constraint = _dereq_('./Constraint');
  2354. var PointToPointConstraint = _dereq_('./PointToPointConstraint');
  2355. var RotationalEquation = _dereq_('../equations/RotationalEquation');
  2356. var RotationalMotorEquation = _dereq_('../equations/RotationalMotorEquation');
  2357. var ContactEquation = _dereq_('../equations/ContactEquation');
  2358. var Vec3 = _dereq_('../math/Vec3');
  2359. /**
  2360. * Lock constraint. Will remove all degrees of freedom between the bodies.
  2361. * @class LockConstraint
  2362. * @constructor
  2363. * @author schteppe
  2364. * @param {Body} bodyA
  2365. * @param {Body} bodyB
  2366. * @param {object} [options]
  2367. * @param {Number} [options.maxForce=1e6]
  2368. * @extends PointToPointConstraint
  2369. */
  2370. function LockConstraint(bodyA, bodyB, options){
  2371. options = options || {};
  2372. var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
  2373. // Set pivot point in between
  2374. var pivotA = new Vec3();
  2375. var pivotB = new Vec3();
  2376. var halfWay = new Vec3();
  2377. bodyA.position.vadd(bodyB.position, halfWay);
  2378. halfWay.scale(0.5, halfWay);
  2379. bodyB.pointToLocalFrame(halfWay, pivotB);
  2380. bodyA.pointToLocalFrame(halfWay, pivotA);
  2381. PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
  2382. /**
  2383. * @property {RotationalEquation} rotationalEquation1
  2384. */
  2385. var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA,bodyB,options);
  2386. /**
  2387. * @property {RotationalEquation} rotationalEquation2
  2388. */
  2389. var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA,bodyB,options);
  2390. /**
  2391. * @property {RotationalEquation} rotationalEquation3
  2392. */
  2393. var r3 = this.rotationalEquation3 = new RotationalEquation(bodyA,bodyB,options);
  2394. this.equations.push(r1, r2, r3);
  2395. }
  2396. LockConstraint.prototype = new PointToPointConstraint();
  2397. LockConstraint.constructor = LockConstraint;
  2398. var LockConstraint_update_tmpVec1 = new Vec3();
  2399. var LockConstraint_update_tmpVec2 = new Vec3();
  2400. LockConstraint.prototype.update = function(){
  2401. var bodyA = this.bodyA,
  2402. bodyB = this.bodyB,
  2403. motor = this.motorEquation,
  2404. r1 = this.rotationalEquation1,
  2405. r2 = this.rotationalEquation2,
  2406. r3 = this.rotationalEquation3,
  2407. worldAxisA = LockConstraint_update_tmpVec1,
  2408. worldAxisB = LockConstraint_update_tmpVec2;
  2409. PointToPointConstraint.prototype.update.call(this);
  2410. bodyA.vectorToWorldFrame(Vec3.UNIT_X, r1.axisA);
  2411. bodyB.vectorToWorldFrame(Vec3.UNIT_Y, r1.axisB);
  2412. bodyA.vectorToWorldFrame(Vec3.UNIT_Y, r2.axisA);
  2413. bodyB.vectorToWorldFrame(Vec3.UNIT_Z, r2.axisB);
  2414. bodyA.vectorToWorldFrame(Vec3.UNIT_Z, r3.axisA);
  2415. bodyB.vectorToWorldFrame(Vec3.UNIT_X, r3.axisB);
  2416. };
  2417. },{"../equations/ContactEquation":19,"../equations/RotationalEquation":22,"../equations/RotationalMotorEquation":23,"../math/Vec3":30,"./Constraint":13,"./PointToPointConstraint":17}],17:[function(_dereq_,module,exports){
  2418. module.exports = PointToPointConstraint;
  2419. var Constraint = _dereq_('./Constraint');
  2420. var ContactEquation = _dereq_('../equations/ContactEquation');
  2421. var Vec3 = _dereq_('../math/Vec3');
  2422. /**
  2423. * Connects two bodies at given offset points.
  2424. * @class PointToPointConstraint
  2425. * @extends Constraint
  2426. * @constructor
  2427. * @param {Body} bodyA
  2428. * @param {Vec3} pivotA The point relative to the center of mass of bodyA which bodyA is constrained to.
  2429. * @param {Body} bodyB Body that will be constrained in a similar way to the same point as bodyA. We will therefore get a link between bodyA and bodyB. If not specified, bodyA will be constrained to a static point.
  2430. * @param {Vec3} pivotB See pivotA.
  2431. * @param {Number} maxForce The maximum force that should be applied to constrain the bodies.
  2432. *
  2433. * @example
  2434. * var bodyA = new Body({ mass: 1 });
  2435. * var bodyB = new Body({ mass: 1 });
  2436. * bodyA.position.set(-1, 0, 0);
  2437. * bodyB.position.set(1, 0, 0);
  2438. * bodyA.addShape(shapeA);
  2439. * bodyB.addShape(shapeB);
  2440. * world.addBody(bodyA);
  2441. * world.addBody(bodyB);
  2442. * var localPivotA = new Vec3(1, 0, 0);
  2443. * var localPivotB = new Vec3(-1, 0, 0);
  2444. * var constraint = new PointToPointConstraint(bodyA, localPivotA, bodyB, localPivotB);
  2445. * world.addConstraint(constraint);
  2446. */
  2447. function PointToPointConstraint(bodyA,pivotA,bodyB,pivotB,maxForce){
  2448. Constraint.call(this,bodyA,bodyB);
  2449. maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
  2450. /**
  2451. * Pivot, defined locally in bodyA.
  2452. * @property {Vec3} pivotA
  2453. */
  2454. this.pivotA = pivotA ? pivotA.clone() : new Vec3();
  2455. /**
  2456. * Pivot, defined locally in bodyB.
  2457. * @property {Vec3} pivotB
  2458. */
  2459. this.pivotB = pivotB ? pivotB.clone() : new Vec3();
  2460. /**
  2461. * @property {ContactEquation} equationX
  2462. */
  2463. var x = this.equationX = new ContactEquation(bodyA,bodyB);
  2464. /**
  2465. * @property {ContactEquation} equationY
  2466. */
  2467. var y = this.equationY = new ContactEquation(bodyA,bodyB);
  2468. /**
  2469. * @property {ContactEquation} equationZ
  2470. */
  2471. var z = this.equationZ = new ContactEquation(bodyA,bodyB);
  2472. // Equations to be fed to the solver
  2473. this.equations.push(x, y, z);
  2474. // Make the equations bidirectional
  2475. x.minForce = y.minForce = z.minForce = -maxForce;
  2476. x.maxForce = y.maxForce = z.maxForce = maxForce;
  2477. x.ni.set(1, 0, 0);
  2478. y.ni.set(0, 1, 0);
  2479. z.ni.set(0, 0, 1);
  2480. }
  2481. PointToPointConstraint.prototype = new Constraint();
  2482. PointToPointConstraint.prototype.update = function(){
  2483. var bodyA = this.bodyA;
  2484. var bodyB = this.bodyB;
  2485. var x = this.equationX;
  2486. var y = this.equationY;
  2487. var z = this.equationZ;
  2488. // Rotate the pivots to world space
  2489. bodyA.quaternion.vmult(this.pivotA,x.ri);
  2490. bodyB.quaternion.vmult(this.pivotB,x.rj);
  2491. y.ri.copy(x.ri);
  2492. y.rj.copy(x.rj);
  2493. z.ri.copy(x.ri);
  2494. z.rj.copy(x.rj);
  2495. };
  2496. },{"../equations/ContactEquation":19,"../math/Vec3":30,"./Constraint":13}],18:[function(_dereq_,module,exports){
  2497. module.exports = ConeEquation;
  2498. var Vec3 = _dereq_('../math/Vec3');
  2499. var Mat3 = _dereq_('../math/Mat3');
  2500. var Equation = _dereq_('./Equation');
  2501. /**
  2502. * Cone equation. Works to keep the given body world vectors aligned, or tilted within a given angle from each other.
  2503. * @class ConeEquation
  2504. * @constructor
  2505. * @author schteppe
  2506. * @param {Body} bodyA
  2507. * @param {Body} bodyB
  2508. * @param {Vec3} [options.axisA] Local axis in A
  2509. * @param {Vec3} [options.axisB] Local axis in B
  2510. * @param {Vec3} [options.angle] The "cone angle" to keep
  2511. * @param {number} [options.maxForce=1e6]
  2512. * @extends Equation
  2513. */
  2514. function ConeEquation(bodyA, bodyB, options){
  2515. options = options || {};
  2516. var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
  2517. Equation.call(this,bodyA,bodyB,-maxForce, maxForce);
  2518. this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
  2519. this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
  2520. /**
  2521. * The cone angle to keep
  2522. * @property {number} angle
  2523. */
  2524. this.angle = typeof(options.angle) !== 'undefined' ? options.angle : 0;
  2525. }
  2526. ConeEquation.prototype = new Equation();
  2527. ConeEquation.prototype.constructor = ConeEquation;
  2528. var tmpVec1 = new Vec3();
  2529. var tmpVec2 = new Vec3();
  2530. ConeEquation.prototype.computeB = function(h){
  2531. var a = this.a,
  2532. b = this.b,
  2533. ni = this.axisA,
  2534. nj = this.axisB,
  2535. nixnj = tmpVec1,
  2536. njxni = tmpVec2,
  2537. GA = this.jacobianElementA,
  2538. GB = this.jacobianElementB;
  2539. // Caluclate cross products
  2540. ni.cross(nj, nixnj);
  2541. nj.cross(ni, njxni);
  2542. // The angle between two vector is:
  2543. // cos(theta) = a * b / (length(a) * length(b) = { len(a) = len(b) = 1 } = a * b
  2544. // g = a * b
  2545. // gdot = (b x a) * wi + (a x b) * wj
  2546. // G = [0 bxa 0 axb]
  2547. // W = [vi wi vj wj]
  2548. GA.rotational.copy(njxni);
  2549. GB.rotational.copy(nixnj);
  2550. var g = Math.cos(this.angle) - ni.dot(nj),
  2551. GW = this.computeGW(),
  2552. GiMf = this.computeGiMf();
  2553. var B = - g * a - GW * b - h * GiMf;
  2554. return B;
  2555. };
  2556. },{"../math/Mat3":27,"../math/Vec3":30,"./Equation":20}],19:[function(_dereq_,module,exports){
  2557. module.exports = ContactEquation;
  2558. var Equation = _dereq_('./Equation');
  2559. var Vec3 = _dereq_('../math/Vec3');
  2560. var Mat3 = _dereq_('../math/Mat3');
  2561. /**
  2562. * Contact/non-penetration constraint equation
  2563. * @class ContactEquation
  2564. * @constructor
  2565. * @author schteppe
  2566. * @param {Body} bodyA
  2567. * @param {Body} bodyB
  2568. * @extends Equation
  2569. */
  2570. function ContactEquation(bodyA, bodyB, maxForce){
  2571. maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
  2572. Equation.call(this, bodyA, bodyB, 0, maxForce);
  2573. /**
  2574. * @property restitution
  2575. * @type {Number}
  2576. */
  2577. this.restitution = 0.0; // "bounciness": u1 = -e*u0
  2578. /**
  2579. * World-oriented vector that goes from the center of bi to the contact point.
  2580. * @property {Vec3} ri
  2581. */
  2582. this.ri = new Vec3();
  2583. /**
  2584. * World-oriented vector that starts in body j position and goes to the contact point.
  2585. * @property {Vec3} rj
  2586. */
  2587. this.rj = new Vec3();
  2588. /**
  2589. * Contact normal, pointing out of body i.
  2590. * @property {Vec3} ni
  2591. */
  2592. this.ni = new Vec3();
  2593. }
  2594. ContactEquation.prototype = new Equation();
  2595. ContactEquation.prototype.constructor = ContactEquation;
  2596. var ContactEquation_computeB_temp1 = new Vec3(); // Temp vectors
  2597. var ContactEquation_computeB_temp2 = new Vec3();
  2598. var ContactEquation_computeB_temp3 = new Vec3();
  2599. ContactEquation.prototype.computeB = function(h){
  2600. var a = this.a,
  2601. b = this.b,
  2602. bi = this.bi,
  2603. bj = this.bj,
  2604. ri = this.ri,
  2605. rj = this.rj,
  2606. rixn = ContactEquation_computeB_temp1,
  2607. rjxn = ContactEquation_computeB_temp2,
  2608. vi = bi.velocity,
  2609. wi = bi.angularVelocity,
  2610. fi = bi.force,
  2611. taui = bi.torque,
  2612. vj = bj.velocity,
  2613. wj = bj.angularVelocity,
  2614. fj = bj.force,
  2615. tauj = bj.torque,
  2616. penetrationVec = ContactEquation_computeB_temp3,
  2617. GA = this.jacobianElementA,
  2618. GB = this.jacobianElementB,
  2619. n = this.ni;
  2620. // Caluclate cross products
  2621. ri.cross(n,rixn);
  2622. rj.cross(n,rjxn);
  2623. // g = xj+rj -(xi+ri)
  2624. // G = [ -ni -rixn ni rjxn ]
  2625. n.negate(GA.spatial);
  2626. rixn.negate(GA.rotational);
  2627. GB.spatial.copy(n);
  2628. GB.rotational.copy(rjxn);
  2629. // Calculate the penetration vector
  2630. penetrationVec.copy(bj.position);
  2631. penetrationVec.vadd(rj,penetrationVec);
  2632. penetrationVec.vsub(bi.position,penetrationVec);
  2633. penetrationVec.vsub(ri,penetrationVec);
  2634. var g = n.dot(penetrationVec);
  2635. // Compute iteration
  2636. var ePlusOne = this.restitution + 1;
  2637. var GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn);
  2638. var GiMf = this.computeGiMf();
  2639. var B = - g * a - GW * b - h*GiMf;
  2640. return B;
  2641. };
  2642. var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3();
  2643. var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3();
  2644. var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3();
  2645. var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3();
  2646. var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3();
  2647. /**
  2648. * Get the current relative velocity in the contact point.
  2649. * @method getImpactVelocityAlongNormal
  2650. * @return {number}
  2651. */
  2652. ContactEquation.prototype.getImpactVelocityAlongNormal = function(){
  2653. var vi = ContactEquation_getImpactVelocityAlongNormal_vi;
  2654. var vj = ContactEquation_getImpactVelocityAlongNormal_vj;
  2655. var xi = ContactEquation_getImpactVelocityAlongNormal_xi;
  2656. var xj = ContactEquation_getImpactVelocityAlongNormal_xj;
  2657. var relVel = ContactEquation_getImpactVelocityAlongNormal_relVel;
  2658. this.bi.position.vadd(this.ri, xi);
  2659. this.bj.position.vadd(this.rj, xj);
  2660. this.bi.getVelocityAtWorldPoint(xi, vi);
  2661. this.bj.getVelocityAtWorldPoint(xj, vj);
  2662. vi.vsub(vj, relVel);
  2663. return this.ni.dot(relVel);
  2664. };
  2665. },{"../math/Mat3":27,"../math/Vec3":30,"./Equation":20}],20:[function(_dereq_,module,exports){
  2666. module.exports = Equation;
  2667. var JacobianElement = _dereq_('../math/JacobianElement'),
  2668. Vec3 = _dereq_('../math/Vec3');
  2669. /**
  2670. * Equation base class
  2671. * @class Equation
  2672. * @constructor
  2673. * @author schteppe
  2674. * @param {Body} bi
  2675. * @param {Body} bj
  2676. * @param {Number} minForce Minimum (read: negative max) force to be applied by the constraint.
  2677. * @param {Number} maxForce Maximum (read: positive max) force to be applied by the constraint.
  2678. */
  2679. function Equation(bi,bj,minForce,maxForce){
  2680. this.id = Equation.id++;
  2681. /**
  2682. * @property {number} minForce
  2683. */
  2684. this.minForce = typeof(minForce)==="undefined" ? -1e6 : minForce;
  2685. /**
  2686. * @property {number} maxForce
  2687. */
  2688. this.maxForce = typeof(maxForce)==="undefined" ? 1e6 : maxForce;
  2689. /**
  2690. * @property bi
  2691. * @type {Body}
  2692. */
  2693. this.bi = bi;
  2694. /**
  2695. * @property bj
  2696. * @type {Body}
  2697. */
  2698. this.bj = bj;
  2699. /**
  2700. * SPOOK parameter
  2701. * @property {number} a
  2702. */
  2703. this.a = 0.0;
  2704. /**
  2705. * SPOOK parameter
  2706. * @property {number} b
  2707. */
  2708. this.b = 0.0;
  2709. /**
  2710. * SPOOK parameter
  2711. * @property {number} eps
  2712. */
  2713. this.eps = 0.0;
  2714. /**
  2715. * @property {JacobianElement} jacobianElementA
  2716. */
  2717. this.jacobianElementA = new JacobianElement();
  2718. /**
  2719. * @property {JacobianElement} jacobianElementB
  2720. */
  2721. this.jacobianElementB = new JacobianElement();
  2722. /**
  2723. * @property {boolean} enabled
  2724. * @default true
  2725. */
  2726. this.enabled = true;
  2727. // Set typical spook params
  2728. this.setSpookParams(1e7,4,1/60);
  2729. }
  2730. Equation.prototype.constructor = Equation;
  2731. Equation.id = 0;
  2732. /**
  2733. * Recalculates a,b,eps.
  2734. * @method setSpookParams
  2735. */
  2736. Equation.prototype.setSpookParams = function(stiffness,relaxation,timeStep){
  2737. var d = relaxation,
  2738. k = stiffness,
  2739. h = timeStep;
  2740. this.a = 4.0 / (h * (1 + 4 * d));
  2741. this.b = (4.0 * d) / (1 + 4 * d);
  2742. this.eps = 4.0 / (h * h * k * (1 + 4 * d));
  2743. };
  2744. /**
  2745. * Computes the RHS of the SPOOK equation
  2746. * @method computeB
  2747. * @return {Number}
  2748. */
  2749. Equation.prototype.computeB = function(a,b,h){
  2750. var GW = this.computeGW(),
  2751. Gq = this.computeGq(),
  2752. GiMf = this.computeGiMf();
  2753. return - Gq * a - GW * b - GiMf*h;
  2754. };
  2755. /**
  2756. * Computes G*q, where q are the generalized body coordinates
  2757. * @method computeGq
  2758. * @return {Number}
  2759. */
  2760. Equation.prototype.computeGq = function(){
  2761. var GA = this.jacobianElementA,
  2762. GB = this.jacobianElementB,
  2763. bi = this.bi,
  2764. bj = this.bj,
  2765. xi = bi.position,
  2766. xj = bj.position;
  2767. return GA.spatial.dot(xi) + GB.spatial.dot(xj);
  2768. };
  2769. var zero = new Vec3();
  2770. /**
  2771. * Computes G*W, where W are the body velocities
  2772. * @method computeGW
  2773. * @return {Number}
  2774. */
  2775. Equation.prototype.computeGW = function(){
  2776. var GA = this.jacobianElementA,
  2777. GB = this.jacobianElementB,
  2778. bi = this.bi,
  2779. bj = this.bj,
  2780. vi = bi.velocity,
  2781. vj = bj.velocity,
  2782. wi = bi.angularVelocity || zero,
  2783. wj = bj.angularVelocity || zero;
  2784. return GA.multiplyVectors(vi,wi) + GB.multiplyVectors(vj,wj);
  2785. };
  2786. /**
  2787. * Computes G*Wlambda, where W are the body velocities
  2788. * @method computeGWlambda
  2789. * @return {Number}
  2790. */
  2791. Equation.prototype.computeGWlambda = function(){
  2792. var GA = this.jacobianElementA,
  2793. GB = this.jacobianElementB,
  2794. bi = this.bi,
  2795. bj = this.bj,
  2796. vi = bi.vlambda,
  2797. vj = bj.vlambda,
  2798. wi = bi.wlambda || zero,
  2799. wj = bj.wlambda || zero;
  2800. return GA.multiplyVectors(vi,wi) + GB.multiplyVectors(vj,wj);
  2801. };
  2802. /**
  2803. * Computes G*inv(M)*f, where M is the mass matrix with diagonal blocks for each body, and f are the forces on the bodies.
  2804. * @method computeGiMf
  2805. * @return {Number}
  2806. */
  2807. var iMfi = new Vec3(),
  2808. iMfj = new Vec3(),
  2809. invIi_vmult_taui = new Vec3(),
  2810. invIj_vmult_tauj = new Vec3();
  2811. Equation.prototype.computeGiMf = function(){
  2812. var GA = this.jacobianElementA,
  2813. GB = this.jacobianElementB,
  2814. bi = this.bi,
  2815. bj = this.bj,
  2816. fi = bi.force,
  2817. ti = bi.torque,
  2818. fj = bj.force,
  2819. tj = bj.torque,
  2820. invMassi = bi.invMassSolve,
  2821. invMassj = bj.invMassSolve;
  2822. if(bi.invInertiaWorldSolve){ bi.invInertiaWorldSolve.vmult(ti,invIi_vmult_taui); }
  2823. else { invIi_vmult_taui.set(0,0,0); }
  2824. if(bj.invInertiaWorldSolve){ bj.invInertiaWorldSolve.vmult(tj,invIj_vmult_tauj); }
  2825. else { invIj_vmult_tauj.set(0,0,0); }
  2826. fi.mult(invMassi,iMfi);
  2827. fj.mult(invMassj,iMfj);
  2828. return GA.multiplyVectors(iMfi,invIi_vmult_taui) + GB.multiplyVectors(iMfj,invIj_vmult_tauj);
  2829. };
  2830. /**
  2831. * Computes G*inv(M)*G'
  2832. * @method computeGiMGt
  2833. * @return {Number}
  2834. */
  2835. var tmp = new Vec3();
  2836. Equation.prototype.computeGiMGt = function(){
  2837. var GA = this.jacobianElementA,
  2838. GB = this.jacobianElementB,
  2839. bi = this.bi,
  2840. bj = this.bj,
  2841. invMassi = bi.invMassSolve,
  2842. invMassj = bj.invMassSolve,
  2843. invIi = bi.invInertiaWorldSolve,
  2844. invIj = bj.invInertiaWorldSolve,
  2845. result = invMassi + invMassj;
  2846. if(invIi){
  2847. invIi.vmult(GA.rotational,tmp);
  2848. result += tmp.dot(GA.rotational);
  2849. }
  2850. if(invIj){
  2851. invIj.vmult(GB.rotational,tmp);
  2852. result += tmp.dot(GB.rotational);
  2853. }
  2854. return result;
  2855. };
  2856. var addToWlambda_temp = new Vec3(),
  2857. addToWlambda_Gi = new Vec3(),
  2858. addToWlambda_Gj = new Vec3(),
  2859. addToWlambda_ri = new Vec3(),
  2860. addToWlambda_rj = new Vec3(),
  2861. addToWlambda_Mdiag = new Vec3();
  2862. /**
  2863. * Add constraint velocity to the bodies.
  2864. * @method addToWlambda
  2865. * @param {Number} deltalambda
  2866. */
  2867. Equation.prototype.addToWlambda = function(deltalambda){
  2868. var GA = this.jacobianElementA,
  2869. GB = this.jacobianElementB,
  2870. bi = this.bi,
  2871. bj = this.bj,
  2872. temp = addToWlambda_temp;
  2873. // Add to linear velocity
  2874. // v_lambda += inv(M) * delta_lamba * G
  2875. GA.spatial.mult(bi.invMassSolve * deltalambda,temp);
  2876. bi.vlambda.vadd(temp, bi.vlambda);
  2877. GB.spatial.mult(bj.invMassSolve * deltalambda,temp);
  2878. bj.vlambda.vadd(temp, bj.vlambda);
  2879. // Add to angular velocity
  2880. if(bi.invInertiaWorldSolve){
  2881. bi.invInertiaWorldSolve.vmult(GA.rotational,temp);
  2882. temp.mult(deltalambda,temp);
  2883. bi.wlambda.vadd(temp,bi.wlambda);
  2884. }
  2885. if(bj.invInertiaWorldSolve){
  2886. bj.invInertiaWorldSolve.vmult(GB.rotational,temp);
  2887. temp.mult(deltalambda,temp);
  2888. bj.wlambda.vadd(temp,bj.wlambda);
  2889. }
  2890. };
  2891. /**
  2892. * Compute the denominator part of the SPOOK equation: C = G*inv(M)*G' + eps
  2893. * @method computeInvC
  2894. * @param {Number} eps
  2895. * @return {Number}
  2896. */
  2897. Equation.prototype.computeC = function(){
  2898. return this.computeGiMGt() + this.eps;
  2899. };
  2900. },{"../math/JacobianElement":26,"../math/Vec3":30}],21:[function(_dereq_,module,exports){
  2901. module.exports = FrictionEquation;
  2902. var Equation = _dereq_('./Equation');
  2903. var Vec3 = _dereq_('../math/Vec3');
  2904. var Mat3 = _dereq_('../math/Mat3');
  2905. /**
  2906. * Constrains the slipping in a contact along a tangent
  2907. * @class FrictionEquation
  2908. * @constructor
  2909. * @author schteppe
  2910. * @param {Body} bodyA
  2911. * @param {Body} bodyB
  2912. * @param {Number} slipForce should be +-F_friction = +-mu * F_normal = +-mu * m * g
  2913. * @extends Equation
  2914. */
  2915. function FrictionEquation(bodyA, bodyB, slipForce){
  2916. Equation.call(this,bodyA, bodyB, -slipForce, slipForce);
  2917. this.ri = new Vec3();
  2918. this.rj = new Vec3();
  2919. this.t = new Vec3(); // tangent
  2920. }
  2921. FrictionEquation.prototype = new Equation();
  2922. FrictionEquation.prototype.constructor = FrictionEquation;
  2923. var FrictionEquation_computeB_temp1 = new Vec3();
  2924. var FrictionEquation_computeB_temp2 = new Vec3();
  2925. FrictionEquation.prototype.computeB = function(h){
  2926. var a = this.a,
  2927. b = this.b,
  2928. bi = this.bi,
  2929. bj = this.bj,
  2930. ri = this.ri,
  2931. rj = this.rj,
  2932. rixt = FrictionEquation_computeB_temp1,
  2933. rjxt = FrictionEquation_computeB_temp2,
  2934. t = this.t;
  2935. // Caluclate cross products
  2936. ri.cross(t,rixt);
  2937. rj.cross(t,rjxt);
  2938. // G = [-t -rixt t rjxt]
  2939. // And remember, this is a pure velocity constraint, g is always zero!
  2940. var GA = this.jacobianElementA,
  2941. GB = this.jacobianElementB;
  2942. t.negate(GA.spatial);
  2943. rixt.negate(GA.rotational);
  2944. GB.spatial.copy(t);
  2945. GB.rotational.copy(rjxt);
  2946. var GW = this.computeGW();
  2947. var GiMf = this.computeGiMf();
  2948. var B = - GW * b - h * GiMf;
  2949. return B;
  2950. };
  2951. },{"../math/Mat3":27,"../math/Vec3":30,"./Equation":20}],22:[function(_dereq_,module,exports){
  2952. module.exports = RotationalEquation;
  2953. var Vec3 = _dereq_('../math/Vec3');
  2954. var Mat3 = _dereq_('../math/Mat3');
  2955. var Equation = _dereq_('./Equation');
  2956. /**
  2957. * Rotational constraint. Works to keep the local vectors orthogonal to each other in world space.
  2958. * @class RotationalEquation
  2959. * @constructor
  2960. * @author schteppe
  2961. * @param {Body} bodyA
  2962. * @param {Body} bodyB
  2963. * @param {Vec3} [options.axisA]
  2964. * @param {Vec3} [options.axisB]
  2965. * @param {number} [options.maxForce]
  2966. * @extends Equation
  2967. */
  2968. function RotationalEquation(bodyA, bodyB, options){
  2969. options = options || {};
  2970. var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
  2971. Equation.call(this,bodyA,bodyB,-maxForce, maxForce);
  2972. this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
  2973. this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
  2974. this.maxAngle = Math.PI / 2;
  2975. }
  2976. RotationalEquation.prototype = new Equation();
  2977. RotationalEquation.prototype.constructor = RotationalEquation;
  2978. var tmpVec1 = new Vec3();
  2979. var tmpVec2 = new Vec3();
  2980. RotationalEquation.prototype.computeB = function(h){
  2981. var a = this.a,
  2982. b = this.b,
  2983. ni = this.axisA,
  2984. nj = this.axisB,
  2985. nixnj = tmpVec1,
  2986. njxni = tmpVec2,
  2987. GA = this.jacobianElementA,
  2988. GB = this.jacobianElementB;
  2989. // Caluclate cross products
  2990. ni.cross(nj, nixnj);
  2991. nj.cross(ni, njxni);
  2992. // g = ni * nj
  2993. // gdot = (nj x ni) * wi + (ni x nj) * wj
  2994. // G = [0 njxni 0 nixnj]
  2995. // W = [vi wi vj wj]
  2996. GA.rotational.copy(njxni);
  2997. GB.rotational.copy(nixnj);
  2998. var g = Math.cos(this.maxAngle) - ni.dot(nj),
  2999. GW = this.computeGW(),
  3000. GiMf = this.computeGiMf();
  3001. var B = - g * a - GW * b - h * GiMf;
  3002. return B;
  3003. };
  3004. },{"../math/Mat3":27,"../math/Vec3":30,"./Equation":20}],23:[function(_dereq_,module,exports){
  3005. module.exports = RotationalMotorEquation;
  3006. var Vec3 = _dereq_('../math/Vec3');
  3007. var Mat3 = _dereq_('../math/Mat3');
  3008. var Equation = _dereq_('./Equation');
  3009. /**
  3010. * Rotational motor constraint. Tries to keep the relative angular velocity of the bodies to a given value.
  3011. * @class RotationalMotorEquation
  3012. * @constructor
  3013. * @author schteppe
  3014. * @param {Body} bodyA
  3015. * @param {Body} bodyB
  3016. * @param {Number} maxForce
  3017. * @extends Equation
  3018. */
  3019. function RotationalMotorEquation(bodyA, bodyB, maxForce){
  3020. maxForce = typeof(maxForce)!=='undefined' ? maxForce : 1e6;
  3021. Equation.call(this,bodyA,bodyB,-maxForce,maxForce);
  3022. /**
  3023. * World oriented rotational axis
  3024. * @property {Vec3} axisA
  3025. */
  3026. this.axisA = new Vec3();
  3027. /**
  3028. * World oriented rotational axis
  3029. * @property {Vec3} axisB
  3030. */
  3031. this.axisB = new Vec3(); // World oriented rotational axis
  3032. /**
  3033. * Motor velocity
  3034. * @property {Number} targetVelocity
  3035. */
  3036. this.targetVelocity = 0;
  3037. }
  3038. RotationalMotorEquation.prototype = new Equation();
  3039. RotationalMotorEquation.prototype.constructor = RotationalMotorEquation;
  3040. RotationalMotorEquation.prototype.computeB = function(h){
  3041. var a = this.a,
  3042. b = this.b,
  3043. bi = this.bi,
  3044. bj = this.bj,
  3045. axisA = this.axisA,
  3046. axisB = this.axisB,
  3047. GA = this.jacobianElementA,
  3048. GB = this.jacobianElementB;
  3049. // g = 0
  3050. // gdot = axisA * wi - axisB * wj
  3051. // gdot = G * W = G * [vi wi vj wj]
  3052. // =>
  3053. // G = [0 axisA 0 -axisB]
  3054. GA.rotational.copy(axisA);
  3055. axisB.negate(GB.rotational);
  3056. var GW = this.computeGW() - this.targetVelocity,
  3057. GiMf = this.computeGiMf();
  3058. var B = - GW * b - h * GiMf;
  3059. return B;
  3060. };
  3061. },{"../math/Mat3":27,"../math/Vec3":30,"./Equation":20}],24:[function(_dereq_,module,exports){
  3062. var Utils = _dereq_('../utils/Utils');
  3063. module.exports = ContactMaterial;
  3064. /**
  3065. * Defines what happens when two materials meet.
  3066. * @class ContactMaterial
  3067. * @constructor
  3068. * @param {Material} m1
  3069. * @param {Material} m2
  3070. * @param {object} [options]
  3071. * @param {Number} [options.friction=0.3]
  3072. * @param {Number} [options.restitution=0.3]
  3073. * @param {number} [options.contactEquationStiffness=1e7]
  3074. * @param {number} [options.contactEquationRelaxation=3]
  3075. * @param {number} [options.frictionEquationStiffness=1e7]
  3076. * @param {Number} [options.frictionEquationRelaxation=3]
  3077. */
  3078. function ContactMaterial(m1, m2, options){
  3079. options = Utils.defaults(options, {
  3080. friction: 0.3,
  3081. restitution: 0.3,
  3082. contactEquationStiffness: 1e7,
  3083. contactEquationRelaxation: 3,
  3084. frictionEquationStiffness: 1e7,
  3085. frictionEquationRelaxation: 3
  3086. });
  3087. /**
  3088. * Identifier of this material
  3089. * @property {Number} id
  3090. */
  3091. this.id = ContactMaterial.idCounter++;
  3092. /**
  3093. * Participating materials
  3094. * @property {Array} materials
  3095. * @todo Should be .materialA and .materialB instead
  3096. */
  3097. this.materials = [m1, m2];
  3098. /**
  3099. * Friction coefficient
  3100. * @property {Number} friction
  3101. */
  3102. this.friction = options.friction;
  3103. /**
  3104. * Restitution coefficient
  3105. * @property {Number} restitution
  3106. */
  3107. this.restitution = options.restitution;
  3108. /**
  3109. * Stiffness of the produced contact equations
  3110. * @property {Number} contactEquationStiffness
  3111. */
  3112. this.contactEquationStiffness = options.contactEquationStiffness;
  3113. /**
  3114. * Relaxation time of the produced contact equations
  3115. * @property {Number} contactEquationRelaxation
  3116. */
  3117. this.contactEquationRelaxation = options.contactEquationRelaxation;
  3118. /**
  3119. * Stiffness of the produced friction equations
  3120. * @property {Number} frictionEquationStiffness
  3121. */
  3122. this.frictionEquationStiffness = options.frictionEquationStiffness;
  3123. /**
  3124. * Relaxation time of the produced friction equations
  3125. * @property {Number} frictionEquationRelaxation
  3126. */
  3127. this.frictionEquationRelaxation = options.frictionEquationRelaxation;
  3128. }
  3129. ContactMaterial.idCounter = 0;
  3130. },{"../utils/Utils":53}],25:[function(_dereq_,module,exports){
  3131. module.exports = Material;
  3132. /**
  3133. * Defines a physics material.
  3134. * @class Material
  3135. * @constructor
  3136. * @param {object} [options]
  3137. * @author schteppe
  3138. */
  3139. function Material(options){
  3140. var name = '';
  3141. options = options || {};
  3142. // Backwards compatibility fix
  3143. if(typeof(options) === 'string'){
  3144. name = options;
  3145. options = {};
  3146. } else if(typeof(options) === 'object') {
  3147. name = '';
  3148. }
  3149. /**
  3150. * @property name
  3151. * @type {String}
  3152. */
  3153. this.name = name;
  3154. /**
  3155. * material id.
  3156. * @property id
  3157. * @type {number}
  3158. */
  3159. this.id = Material.idCounter++;
  3160. /**
  3161. * Friction for this material. If non-negative, it will be used instead of the friction given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used.
  3162. * @property {number} friction
  3163. * miner 修改默认的摩擦力
  3164. */
  3165. this.friction = typeof(options.friction) !== 'undefined' ? options.friction : -1;
  3166. /**
  3167. * Restitution for this material. If non-negative, it will be used instead of the restitution given by ContactMaterials. If there's no matching ContactMaterial, the value from .defaultContactMaterial in the World will be used.
  3168. * @property {number} restitution
  3169. * miner 修改默认的弹力
  3170. */
  3171. this.restitution = typeof(options.restitution) !== 'undefined' ? options.restitution : -1;
  3172. }
  3173. Material.idCounter = 0;
  3174. },{}],26:[function(_dereq_,module,exports){
  3175. module.exports = JacobianElement;
  3176. var Vec3 = _dereq_('./Vec3');
  3177. /**
  3178. * An element containing 6 entries, 3 spatial and 3 rotational degrees of freedom.
  3179. * @class JacobianElement
  3180. * @constructor
  3181. */
  3182. function JacobianElement(){
  3183. /**
  3184. * @property {Vec3} spatial
  3185. */
  3186. this.spatial = new Vec3();
  3187. /**
  3188. * @property {Vec3} rotational
  3189. */
  3190. this.rotational = new Vec3();
  3191. }
  3192. /**
  3193. * Multiply with other JacobianElement
  3194. * @method multiplyElement
  3195. * @param {JacobianElement} element
  3196. * @return {Number}
  3197. */
  3198. JacobianElement.prototype.multiplyElement = function(element){
  3199. return element.spatial.dot(this.spatial) + element.rotational.dot(this.rotational);
  3200. };
  3201. /**
  3202. * Multiply with two vectors
  3203. * @method multiplyVectors
  3204. * @param {Vec3} spatial
  3205. * @param {Vec3} rotational
  3206. * @return {Number}
  3207. */
  3208. JacobianElement.prototype.multiplyVectors = function(spatial,rotational){
  3209. return spatial.dot(this.spatial) + rotational.dot(this.rotational);
  3210. };
  3211. },{"./Vec3":30}],27:[function(_dereq_,module,exports){
  3212. module.exports = Mat3;
  3213. var Vec3 = _dereq_('./Vec3');
  3214. /**
  3215. * A 3x3 matrix.
  3216. * @class Mat3
  3217. * @constructor
  3218. * @param array elements Array of nine elements. Optional.
  3219. * @author schteppe / http://github.com/schteppe
  3220. */
  3221. function Mat3(elements){
  3222. /**
  3223. * A vector of length 9, containing all matrix elements
  3224. * @property {Array} elements
  3225. */
  3226. if(elements){
  3227. this.elements = elements;
  3228. } else {
  3229. this.elements = [0,0,0,0,0,0,0,0,0];
  3230. }
  3231. }
  3232. /**
  3233. * Sets the matrix to identity
  3234. * @method identity
  3235. * @todo Should perhaps be renamed to setIdentity() to be more clear.
  3236. * @todo Create another function that immediately creates an identity matrix eg. eye()
  3237. */
  3238. Mat3.prototype.identity = function(){
  3239. var e = this.elements;
  3240. e[0] = 1;
  3241. e[1] = 0;
  3242. e[2] = 0;
  3243. e[3] = 0;
  3244. e[4] = 1;
  3245. e[5] = 0;
  3246. e[6] = 0;
  3247. e[7] = 0;
  3248. e[8] = 1;
  3249. };
  3250. /**
  3251. * Set all elements to zero
  3252. * @method setZero
  3253. */
  3254. Mat3.prototype.setZero = function(){
  3255. var e = this.elements;
  3256. e[0] = 0;
  3257. e[1] = 0;
  3258. e[2] = 0;
  3259. e[3] = 0;
  3260. e[4] = 0;
  3261. e[5] = 0;
  3262. e[6] = 0;
  3263. e[7] = 0;
  3264. e[8] = 0;
  3265. };
  3266. /**
  3267. * Sets the matrix diagonal elements from a Vec3
  3268. * @method setTrace
  3269. * @param {Vec3} vec3
  3270. */
  3271. Mat3.prototype.setTrace = function(vec3){
  3272. var e = this.elements;
  3273. e[0] = vec3.x;
  3274. e[4] = vec3.y;
  3275. e[8] = vec3.z;
  3276. };
  3277. /**
  3278. * Gets the matrix diagonal elements
  3279. * @method getTrace
  3280. * @return {Vec3}
  3281. */
  3282. Mat3.prototype.getTrace = function(target){
  3283. var target = target || new Vec3();
  3284. var e = this.elements;
  3285. target.x = e[0];
  3286. target.y = e[4];
  3287. target.z = e[8];
  3288. };
  3289. /**
  3290. * Matrix-Vector multiplication
  3291. * @method vmult
  3292. * @param {Vec3} v The vector to multiply with
  3293. * @param {Vec3} target Optional, target to save the result in.
  3294. */
  3295. Mat3.prototype.vmult = function(v,target){
  3296. target = target || new Vec3();
  3297. var e = this.elements,
  3298. x = v.x,
  3299. y = v.y,
  3300. z = v.z;
  3301. target.x = e[0]*x + e[1]*y + e[2]*z;
  3302. target.y = e[3]*x + e[4]*y + e[5]*z;
  3303. target.z = e[6]*x + e[7]*y + e[8]*z;
  3304. return target;
  3305. };
  3306. /**
  3307. * Matrix-scalar multiplication
  3308. * @method smult
  3309. * @param {Number} s
  3310. */
  3311. Mat3.prototype.smult = function(s){
  3312. for(var i=0; i<this.elements.length; i++){
  3313. this.elements[i] *= s;
  3314. }
  3315. };
  3316. /**
  3317. * Matrix multiplication
  3318. * @method mmult
  3319. * @param {Mat3} m Matrix to multiply with from left side.
  3320. * @return {Mat3} The result.
  3321. */
  3322. Mat3.prototype.mmult = function(m,target){
  3323. var r = target || new Mat3();
  3324. for(var i=0; i<3; i++){
  3325. for(var j=0; j<3; j++){
  3326. var sum = 0.0;
  3327. for(var k=0; k<3; k++){
  3328. sum += m.elements[i+k*3] * this.elements[k+j*3];
  3329. }
  3330. r.elements[i+j*3] = sum;
  3331. }
  3332. }
  3333. return r;
  3334. };
  3335. /**
  3336. * Scale each column of the matrix
  3337. * @method scale
  3338. * @param {Vec3} v
  3339. * @return {Mat3} The result.
  3340. */
  3341. Mat3.prototype.scale = function(v,target){
  3342. target = target || new Mat3();
  3343. var e = this.elements,
  3344. t = target.elements;
  3345. for(var i=0; i!==3; i++){
  3346. t[3*i + 0] = v.x * e[3*i + 0];
  3347. t[3*i + 1] = v.y * e[3*i + 1];
  3348. t[3*i + 2] = v.z * e[3*i + 2];
  3349. }
  3350. return target;
  3351. };
  3352. /**
  3353. * Solve Ax=b
  3354. * @method solve
  3355. * @param {Vec3} b The right hand side
  3356. * @param {Vec3} target Optional. Target vector to save in.
  3357. * @return {Vec3} The solution x
  3358. * @todo should reuse arrays
  3359. */
  3360. Mat3.prototype.solve = function(b,target){
  3361. target = target || new Vec3();
  3362. // Construct equations
  3363. var nr = 3; // num rows
  3364. var nc = 4; // num cols
  3365. var eqns = [];
  3366. for(var i=0; i<nr*nc; i++){
  3367. eqns.push(0);
  3368. }
  3369. var i,j;
  3370. for(i=0; i<3; i++){
  3371. for(j=0; j<3; j++){
  3372. eqns[i+nc*j] = this.elements[i+3*j];
  3373. }
  3374. }
  3375. eqns[3+4*0] = b.x;
  3376. eqns[3+4*1] = b.y;
  3377. eqns[3+4*2] = b.z;
  3378. // Compute right upper triangular version of the matrix - Gauss elimination
  3379. var n = 3, k = n, np;
  3380. var kp = 4; // num rows
  3381. var p, els;
  3382. do {
  3383. i = k - n;
  3384. if (eqns[i+nc*i] === 0) {
  3385. // the pivot is null, swap lines
  3386. for (j = i + 1; j < k; j++) {
  3387. if (eqns[i+nc*j] !== 0) {
  3388. np = kp;
  3389. do { // do ligne( i ) = ligne( i ) + ligne( k )
  3390. p = kp - np;
  3391. eqns[p+nc*i] += eqns[p+nc*j];
  3392. } while (--np);
  3393. break;
  3394. }
  3395. }
  3396. }
  3397. if (eqns[i+nc*i] !== 0) {
  3398. for (j = i + 1; j < k; j++) {
  3399. var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
  3400. np = kp;
  3401. do { // do ligne( k ) = ligne( k ) - multiplier * ligne( i )
  3402. p = kp - np;
  3403. eqns[p+nc*j] = p <= i ? 0 : eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
  3404. } while (--np);
  3405. }
  3406. }
  3407. } while (--n);
  3408. // Get the solution
  3409. target.z = eqns[2*nc+3] / eqns[2*nc+2];
  3410. target.y = (eqns[1*nc+3] - eqns[1*nc+2]*target.z) / eqns[1*nc+1];
  3411. target.x = (eqns[0*nc+3] - eqns[0*nc+2]*target.z - eqns[0*nc+1]*target.y) / eqns[0*nc+0];
  3412. if(isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || target.x===Infinity || target.y===Infinity || target.z===Infinity){
  3413. throw "Could not solve equation! Got x=["+target.toString()+"], b=["+b.toString()+"], A=["+this.toString()+"]";
  3414. }
  3415. return target;
  3416. };
  3417. /**
  3418. * Get an element in the matrix by index. Index starts at 0, not 1!!!
  3419. * @method e
  3420. * @param {Number} row
  3421. * @param {Number} column
  3422. * @param {Number} value Optional. If provided, the matrix element will be set to this value.
  3423. * @return {Number}
  3424. */
  3425. Mat3.prototype.e = function( row , column ,value){
  3426. if(value===undefined){
  3427. return this.elements[column+3*row];
  3428. } else {
  3429. // Set value
  3430. this.elements[column+3*row] = value;
  3431. }
  3432. };
  3433. /**
  3434. * Copy another matrix into this matrix object.
  3435. * @method copy
  3436. * @param {Mat3} source
  3437. * @return {Mat3} this
  3438. */
  3439. Mat3.prototype.copy = function(source){
  3440. for(var i=0; i < source.elements.length; i++){
  3441. this.elements[i] = source.elements[i];
  3442. }
  3443. return this;
  3444. };
  3445. /**
  3446. * Returns a string representation of the matrix.
  3447. * @method toString
  3448. * @return string
  3449. */
  3450. Mat3.prototype.toString = function(){
  3451. var r = "";
  3452. var sep = ",";
  3453. for(var i=0; i<9; i++){
  3454. r += this.elements[i] + sep;
  3455. }
  3456. return r;
  3457. };
  3458. /**
  3459. * reverse the matrix
  3460. * @method reverse
  3461. * @param {Mat3} target Optional. Target matrix to save in.
  3462. * @return {Mat3} The solution x
  3463. */
  3464. Mat3.prototype.reverse = function(target){
  3465. target = target || new Mat3();
  3466. // Construct equations
  3467. var nr = 3; // num rows
  3468. var nc = 6; // num cols
  3469. var eqns = [];
  3470. for(var i=0; i<nr*nc; i++){
  3471. eqns.push(0);
  3472. }
  3473. var i,j;
  3474. for(i=0; i<3; i++){
  3475. for(j=0; j<3; j++){
  3476. eqns[i+nc*j] = this.elements[i+3*j];
  3477. }
  3478. }
  3479. eqns[3+6*0] = 1;
  3480. eqns[3+6*1] = 0;
  3481. eqns[3+6*2] = 0;
  3482. eqns[4+6*0] = 0;
  3483. eqns[4+6*1] = 1;
  3484. eqns[4+6*2] = 0;
  3485. eqns[5+6*0] = 0;
  3486. eqns[5+6*1] = 0;
  3487. eqns[5+6*2] = 1;
  3488. // Compute right upper triangular version of the matrix - Gauss elimination
  3489. var n = 3, k = n, np;
  3490. var kp = nc; // num rows
  3491. var p;
  3492. do {
  3493. i = k - n;
  3494. if (eqns[i+nc*i] === 0) {
  3495. // the pivot is null, swap lines
  3496. for (j = i + 1; j < k; j++) {
  3497. if (eqns[i+nc*j] !== 0) {
  3498. np = kp;
  3499. do { // do line( i ) = line( i ) + line( k )
  3500. p = kp - np;
  3501. eqns[p+nc*i] += eqns[p+nc*j];
  3502. } while (--np);
  3503. break;
  3504. }
  3505. }
  3506. }
  3507. if (eqns[i+nc*i] !== 0) {
  3508. for (j = i + 1; j < k; j++) {
  3509. var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
  3510. np = kp;
  3511. do { // do line( k ) = line( k ) - multiplier * line( i )
  3512. p = kp - np;
  3513. eqns[p+nc*j] = p <= i ? 0 : eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
  3514. } while (--np);
  3515. }
  3516. }
  3517. } while (--n);
  3518. // eliminate the upper left triangle of the matrix
  3519. i = 2;
  3520. do {
  3521. j = i-1;
  3522. do {
  3523. var multiplier = eqns[i+nc*j] / eqns[i+nc*i];
  3524. np = nc;
  3525. do {
  3526. p = nc - np;
  3527. eqns[p+nc*j] = eqns[p+nc*j] - eqns[p+nc*i] * multiplier ;
  3528. } while (--np);
  3529. } while (j--);
  3530. } while (--i);
  3531. // operations on the diagonal
  3532. i = 2;
  3533. do {
  3534. var multiplier = 1 / eqns[i+nc*i];
  3535. np = nc;
  3536. do {
  3537. p = nc - np;
  3538. eqns[p+nc*i] = eqns[p+nc*i] * multiplier ;
  3539. } while (--np);
  3540. } while (i--);
  3541. i = 2;
  3542. do {
  3543. j = 2;
  3544. do {
  3545. p = eqns[nr+j+nc*i];
  3546. if( isNaN( p ) || p ===Infinity ){
  3547. throw "Could not reverse! A=["+this.toString()+"]";
  3548. }
  3549. target.e( i , j , p );
  3550. } while (j--);
  3551. } while (i--);
  3552. return target;
  3553. };
  3554. /**
  3555. * Set the matrix from a quaterion
  3556. * @method setRotationFromQuaternion
  3557. * @param {Quaternion} q
  3558. */
  3559. Mat3.prototype.setRotationFromQuaternion = function( q ) {
  3560. var x = q.x, y = q.y, z = q.z, w = q.w,
  3561. x2 = x + x, y2 = y + y, z2 = z + z,
  3562. xx = x * x2, xy = x * y2, xz = x * z2,
  3563. yy = y * y2, yz = y * z2, zz = z * z2,
  3564. wx = w * x2, wy = w * y2, wz = w * z2,
  3565. e = this.elements;
  3566. e[3*0 + 0] = 1 - ( yy + zz );
  3567. e[3*0 + 1] = xy - wz;
  3568. e[3*0 + 2] = xz + wy;
  3569. e[3*1 + 0] = xy + wz;
  3570. e[3*1 + 1] = 1 - ( xx + zz );
  3571. e[3*1 + 2] = yz - wx;
  3572. e[3*2 + 0] = xz - wy;
  3573. e[3*2 + 1] = yz + wx;
  3574. e[3*2 + 2] = 1 - ( xx + yy );
  3575. return this;
  3576. };
  3577. /**
  3578. * Transpose the matrix
  3579. * @method transpose
  3580. * @param {Mat3} target Where to store the result.
  3581. * @return {Mat3} The target Mat3, or a new Mat3 if target was omitted.
  3582. */
  3583. Mat3.prototype.transpose = function( target ) {
  3584. target = target || new Mat3();
  3585. var Mt = target.elements,
  3586. M = this.elements;
  3587. for(var i=0; i!==3; i++){
  3588. for(var j=0; j!==3; j++){
  3589. Mt[3*i + j] = M[3*j + i];
  3590. }
  3591. }
  3592. return target;
  3593. };
  3594. },{"./Vec3":30}],28:[function(_dereq_,module,exports){
  3595. module.exports = Quaternion;
  3596. var Vec3 = _dereq_('./Vec3');
  3597. /**
  3598. * A Quaternion describes a rotation in 3D space. The Quaternion is mathematically defined as Q = x*i + y*j + z*k + w, where (i,j,k) are imaginary basis vectors. (x,y,z) can be seen as a vector related to the axis of rotation, while the real multiplier, w, is related to the amount of rotation.
  3599. * @class Quaternion
  3600. * @constructor
  3601. * @param {Number} x Multiplier of the imaginary basis vector i.
  3602. * @param {Number} y Multiplier of the imaginary basis vector j.
  3603. * @param {Number} z Multiplier of the imaginary basis vector k.
  3604. * @param {Number} w Multiplier of the real part.
  3605. * @see http://en.wikipedia.org/wiki/Quaternion
  3606. */
  3607. function Quaternion(x,y,z,w){
  3608. /**
  3609. * @property {Number} x
  3610. */
  3611. this.x = x!==undefined ? x : 0;
  3612. /**
  3613. * @property {Number} y
  3614. */
  3615. this.y = y!==undefined ? y : 0;
  3616. /**
  3617. * @property {Number} z
  3618. */
  3619. this.z = z!==undefined ? z : 0;
  3620. /**
  3621. * The multiplier of the real quaternion basis vector.
  3622. * @property {Number} w
  3623. */
  3624. this.w = w!==undefined ? w : 1;
  3625. }
  3626. /**
  3627. * Set the value of the quaternion.
  3628. * @method set
  3629. * @param {Number} x
  3630. * @param {Number} y
  3631. * @param {Number} z
  3632. * @param {Number} w
  3633. */
  3634. Quaternion.prototype.set = function(x,y,z,w){
  3635. this.x = x;
  3636. this.y = y;
  3637. this.z = z;
  3638. this.w = w;
  3639. };
  3640. /**
  3641. * Convert to a readable format
  3642. * @method toString
  3643. * @return string
  3644. */
  3645. Quaternion.prototype.toString = function(){
  3646. return this.x+","+this.y+","+this.z+","+this.w;
  3647. };
  3648. /**
  3649. * Convert to an Array
  3650. * @method toArray
  3651. * @return Array
  3652. */
  3653. Quaternion.prototype.toArray = function(){
  3654. return [this.x, this.y, this.z, this.w];
  3655. };
  3656. /**
  3657. * Set the quaternion components given an axis and an angle.
  3658. * @method setFromAxisAngle
  3659. * @param {Vec3} axis
  3660. * @param {Number} angle in radians
  3661. */
  3662. Quaternion.prototype.setFromAxisAngle = function(axis,angle){
  3663. var s = Math.sin(angle*0.5);
  3664. this.x = axis.x * s;
  3665. this.y = axis.y * s;
  3666. this.z = axis.z * s;
  3667. this.w = Math.cos(angle*0.5);
  3668. };
  3669. /**
  3670. * Converts the quaternion to axis/angle representation.
  3671. * @method toAxisAngle
  3672. * @param {Vec3} targetAxis Optional. A vector object to reuse for storing the axis.
  3673. * @return Array An array, first elemnt is the axis and the second is the angle in radians.
  3674. */
  3675. Quaternion.prototype.toAxisAngle = function(targetAxis){
  3676. targetAxis = targetAxis || new Vec3();
  3677. this.normalize(); // if w>1 acos and sqrt will produce errors, this cant happen if quaternion is normalised
  3678. var angle = 2 * Math.acos(this.w);
  3679. var s = Math.sqrt(1-this.w*this.w); // assuming quaternion normalised then w is less than 1, so term always positive.
  3680. if (s < 0.001) { // test to avoid divide by zero, s is always positive due to sqrt
  3681. // if s close to zero then direction of axis not important
  3682. targetAxis.x = this.x; // if it is important that axis is normalised then replace with x=1; y=z=0;
  3683. targetAxis.y = this.y;
  3684. targetAxis.z = this.z;
  3685. } else {
  3686. targetAxis.x = this.x / s; // normalise axis
  3687. targetAxis.y = this.y / s;
  3688. targetAxis.z = this.z / s;
  3689. }
  3690. return [targetAxis,angle];
  3691. };
  3692. var sfv_t1 = new Vec3(),
  3693. sfv_t2 = new Vec3();
  3694. /**
  3695. * Set the quaternion value given two vectors. The resulting rotation will be the needed rotation to rotate u to v.
  3696. * @method setFromVectors
  3697. * @param {Vec3} u
  3698. * @param {Vec3} v
  3699. */
  3700. Quaternion.prototype.setFromVectors = function(u,v){
  3701. if(u.isAntiparallelTo(v)){
  3702. var t1 = sfv_t1;
  3703. var t2 = sfv_t2;
  3704. u.tangents(t1,t2);
  3705. this.setFromAxisAngle(t1,Math.PI);
  3706. } else {
  3707. var a = u.cross(v);
  3708. this.x = a.x;
  3709. this.y = a.y;
  3710. this.z = a.z;
  3711. this.w = Math.sqrt(Math.pow(u.norm(),2) * Math.pow(v.norm(),2)) + u.dot(v);
  3712. this.normalize();
  3713. }
  3714. };
  3715. /**
  3716. * Quaternion multiplication
  3717. * @method mult
  3718. * @param {Quaternion} q
  3719. * @param {Quaternion} target Optional.
  3720. * @return {Quaternion}
  3721. */
  3722. var Quaternion_mult_va = new Vec3();
  3723. var Quaternion_mult_vb = new Vec3();
  3724. var Quaternion_mult_vaxvb = new Vec3();
  3725. Quaternion.prototype.mult = function(q,target){
  3726. target = target || new Quaternion();
  3727. var w = this.w,
  3728. va = Quaternion_mult_va,
  3729. vb = Quaternion_mult_vb,
  3730. vaxvb = Quaternion_mult_vaxvb;
  3731. va.set(this.x,this.y,this.z);
  3732. vb.set(q.x,q.y,q.z);
  3733. target.w = w*q.w - va.dot(vb);
  3734. va.cross(vb,vaxvb);
  3735. target.x = w * vb.x + q.w*va.x + vaxvb.x;
  3736. target.y = w * vb.y + q.w*va.y + vaxvb.y;
  3737. target.z = w * vb.z + q.w*va.z + vaxvb.z;
  3738. return target;
  3739. };
  3740. /**
  3741. * Get the inverse quaternion rotation.
  3742. * @method inverse
  3743. * @param {Quaternion} target
  3744. * @return {Quaternion}
  3745. */
  3746. Quaternion.prototype.inverse = function(target){
  3747. var x = this.x, y = this.y, z = this.z, w = this.w;
  3748. target = target || new Quaternion();
  3749. this.conjugate(target);
  3750. var inorm2 = 1/(x*x + y*y + z*z + w*w);
  3751. target.x *= inorm2;
  3752. target.y *= inorm2;
  3753. target.z *= inorm2;
  3754. target.w *= inorm2;
  3755. return target;
  3756. };
  3757. /**
  3758. * Get the quaternion conjugate
  3759. * @method conjugate
  3760. * @param {Quaternion} target
  3761. * @return {Quaternion}
  3762. */
  3763. Quaternion.prototype.conjugate = function(target){
  3764. target = target || new Quaternion();
  3765. target.x = -this.x;
  3766. target.y = -this.y;
  3767. target.z = -this.z;
  3768. target.w = this.w;
  3769. return target;
  3770. };
  3771. /**
  3772. * Normalize the quaternion. Note that this changes the values of the quaternion.
  3773. * @method normalize
  3774. */
  3775. Quaternion.prototype.normalize = function(){
  3776. var l = Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);
  3777. if ( l === 0 ) {
  3778. this.x = 0;
  3779. this.y = 0;
  3780. this.z = 0;
  3781. this.w = 0;
  3782. } else {
  3783. l = 1 / l;
  3784. this.x *= l;
  3785. this.y *= l;
  3786. this.z *= l;
  3787. this.w *= l;
  3788. }
  3789. };
  3790. /**
  3791. * Approximation of quaternion normalization. Works best when quat is already almost-normalized.
  3792. * @method normalizeFast
  3793. * @see http://jsperf.com/fast-quaternion-normalization
  3794. * @author unphased, https://github.com/unphased
  3795. */
  3796. Quaternion.prototype.normalizeFast = function () {
  3797. var f = (3.0-(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w))/2.0;
  3798. if ( f === 0 ) {
  3799. this.x = 0;
  3800. this.y = 0;
  3801. this.z = 0;
  3802. this.w = 0;
  3803. } else {
  3804. this.x *= f;
  3805. this.y *= f;
  3806. this.z *= f;
  3807. this.w *= f;
  3808. }
  3809. };
  3810. /**
  3811. * Multiply the quaternion by a vector
  3812. * @method vmult
  3813. * @param {Vec3} v
  3814. * @param {Vec3} target Optional
  3815. * @return {Vec3}
  3816. */
  3817. Quaternion.prototype.vmult = function(v,target){
  3818. target = target || new Vec3();
  3819. var x = v.x,
  3820. y = v.y,
  3821. z = v.z;
  3822. var qx = this.x,
  3823. qy = this.y,
  3824. qz = this.z,
  3825. qw = this.w;
  3826. // q*v
  3827. var ix = qw * x + qy * z - qz * y,
  3828. iy = qw * y + qz * x - qx * z,
  3829. iz = qw * z + qx * y - qy * x,
  3830. iw = -qx * x - qy * y - qz * z;
  3831. target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
  3832. target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
  3833. target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
  3834. return target;
  3835. };
  3836. /**
  3837. * Copies value of source to this quaternion.
  3838. * @method copy
  3839. * @param {Quaternion} source
  3840. * @return {Quaternion} this
  3841. */
  3842. Quaternion.prototype.copy = function(source){
  3843. this.x = source.x;
  3844. this.y = source.y;
  3845. this.z = source.z;
  3846. this.w = source.w;
  3847. return this;
  3848. };
  3849. /**
  3850. * Convert the quaternion to euler angle representation. Order: YZX, as this page describes: http://www.euclideanspace.com/maths/standards/index.htm
  3851. * @method toEuler
  3852. * @param {Vec3} target
  3853. * @param string order Three-character string e.g. "YZX", which also is default.
  3854. */
  3855. Quaternion.prototype.toEuler = function(target,order){
  3856. order = order || "YZX";
  3857. var heading, attitude, bank;
  3858. var x = this.x, y = this.y, z = this.z, w = this.w;
  3859. switch(order){
  3860. case "YZX":
  3861. var test = x*y + z*w;
  3862. if (test > 0.499) { // singularity at north pole
  3863. heading = 2 * Math.atan2(x,w);
  3864. attitude = Math.PI/2;
  3865. bank = 0;
  3866. }
  3867. if (test < -0.499) { // singularity at south pole
  3868. heading = -2 * Math.atan2(x,w);
  3869. attitude = - Math.PI/2;
  3870. bank = 0;
  3871. }
  3872. if(isNaN(heading)){
  3873. var sqx = x*x;
  3874. var sqy = y*y;
  3875. var sqz = z*z;
  3876. heading = Math.atan2(2*y*w - 2*x*z , 1 - 2*sqy - 2*sqz); // Heading
  3877. attitude = Math.asin(2*test); // attitude
  3878. bank = Math.atan2(2*x*w - 2*y*z , 1 - 2*sqx - 2*sqz); // bank
  3879. }
  3880. break;
  3881. default:
  3882. throw new Error("Euler order "+order+" not supported yet.");
  3883. }
  3884. target.y = heading;
  3885. target.z = attitude;
  3886. target.x = bank;
  3887. };
  3888. /**
  3889. * See http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
  3890. * @method setFromEuler
  3891. * @param {Number} x
  3892. * @param {Number} y
  3893. * @param {Number} z
  3894. * @param {String} order The order to apply angles: 'XYZ' or 'YXZ' or any other combination
  3895. */
  3896. Quaternion.prototype.setFromEuler = function ( x, y, z, order ) {
  3897. order = order || "XYZ";
  3898. var c1 = Math.cos( x / 2 );
  3899. var c2 = Math.cos( y / 2 );
  3900. var c3 = Math.cos( z / 2 );
  3901. var s1 = Math.sin( x / 2 );
  3902. var s2 = Math.sin( y / 2 );
  3903. var s3 = Math.sin( z / 2 );
  3904. if ( order === 'XYZ' ) {
  3905. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  3906. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  3907. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  3908. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  3909. } else if ( order === 'YXZ' ) {
  3910. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  3911. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  3912. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  3913. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  3914. } else if ( order === 'ZXY' ) {
  3915. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  3916. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  3917. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  3918. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  3919. } else if ( order === 'ZYX' ) {
  3920. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  3921. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  3922. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  3923. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  3924. } else if ( order === 'YZX' ) {
  3925. this.x = s1 * c2 * c3 + c1 * s2 * s3;
  3926. this.y = c1 * s2 * c3 + s1 * c2 * s3;
  3927. this.z = c1 * c2 * s3 - s1 * s2 * c3;
  3928. this.w = c1 * c2 * c3 - s1 * s2 * s3;
  3929. } else if ( order === 'XZY' ) {
  3930. this.x = s1 * c2 * c3 - c1 * s2 * s3;
  3931. this.y = c1 * s2 * c3 - s1 * c2 * s3;
  3932. this.z = c1 * c2 * s3 + s1 * s2 * c3;
  3933. this.w = c1 * c2 * c3 + s1 * s2 * s3;
  3934. }
  3935. return this;
  3936. };
  3937. Quaternion.prototype.clone = function(){
  3938. return new Quaternion(this.x, this.y, this.z, this.w);
  3939. };
  3940. },{"./Vec3":30}],29:[function(_dereq_,module,exports){
  3941. var Vec3 = _dereq_('./Vec3');
  3942. var Quaternion = _dereq_('./Quaternion');
  3943. module.exports = Transform;
  3944. /**
  3945. * @class Transform
  3946. * @constructor
  3947. */
  3948. function Transform(options) {
  3949. options = options || {};
  3950. /**
  3951. * @property {Vec3} position
  3952. */
  3953. this.position = new Vec3();
  3954. if(options.position){
  3955. this.position.copy(options.position);
  3956. }
  3957. /**
  3958. * @property {Quaternion} quaternion
  3959. */
  3960. this.quaternion = new Quaternion();
  3961. if(options.quaternion){
  3962. this.quaternion.copy(options.quaternion);
  3963. }
  3964. }
  3965. var tmpQuat = new Quaternion();
  3966. /**
  3967. * @static
  3968. * @method pointToLocaFrame
  3969. * @param {Vec3} position
  3970. * @param {Quaternion} quaternion
  3971. * @param {Vec3} worldPoint
  3972. * @param {Vec3} result
  3973. */
  3974. Transform.pointToLocalFrame = function(position, quaternion, worldPoint, result){
  3975. var result = result || new Vec3();
  3976. worldPoint.vsub(position, result);
  3977. quaternion.conjugate(tmpQuat);
  3978. tmpQuat.vmult(result, result);
  3979. return result;
  3980. };
  3981. /**
  3982. * Get a global point in local transform coordinates.
  3983. * @method pointToLocal
  3984. * @param {Vec3} point
  3985. * @param {Vec3} result
  3986. * @return {Vec3} The "result" vector object
  3987. */
  3988. Transform.prototype.pointToLocal = function(worldPoint, result){
  3989. return Transform.pointToLocalFrame(this.position, this.quaternion, worldPoint, result);
  3990. };
  3991. /**
  3992. * @static
  3993. * @method pointToWorldFrame
  3994. * @param {Vec3} position
  3995. * @param {Vec3} quaternion
  3996. * @param {Vec3} localPoint
  3997. * @param {Vec3} result
  3998. */
  3999. Transform.pointToWorldFrame = function(position, quaternion, localPoint, result){
  4000. var result = result || new Vec3();
  4001. quaternion.vmult(localPoint, result);
  4002. result.vadd(position, result);
  4003. return result;
  4004. };
  4005. /**
  4006. * Get a local point in global transform coordinates.
  4007. * @method pointToWorld
  4008. * @param {Vec3} point
  4009. * @param {Vec3} result
  4010. * @return {Vec3} The "result" vector object
  4011. */
  4012. Transform.prototype.pointToWorld = function(localPoint, result){
  4013. return Transform.pointToWorldFrame(this.position, this.quaternion, localPoint, result);
  4014. };
  4015. Transform.prototype.vectorToWorldFrame = function(localVector, result){
  4016. var result = result || new Vec3();
  4017. this.quaternion.vmult(localVector, result);
  4018. return result;
  4019. };
  4020. Transform.vectorToWorldFrame = function(quaternion, localVector, result){
  4021. quaternion.vmult(localVector, result);
  4022. return result;
  4023. };
  4024. Transform.vectorToLocalFrame = function(position, quaternion, worldVector, result){
  4025. var result = result || new Vec3();
  4026. quaternion.w *= -1;
  4027. quaternion.vmult(worldVector, result);
  4028. quaternion.w *= -1;
  4029. return result;
  4030. };
  4031. },{"./Quaternion":28,"./Vec3":30}],30:[function(_dereq_,module,exports){
  4032. module.exports = Vec3;
  4033. var Mat3 = _dereq_('./Mat3');
  4034. /**
  4035. * 3-dimensional vector
  4036. * @class Vec3
  4037. * @constructor
  4038. * @param {Number} x
  4039. * @param {Number} y
  4040. * @param {Number} z
  4041. * @author schteppe
  4042. * @example
  4043. * var v = new Vec3(1, 2, 3);
  4044. * console.log('x=' + v.x); // x=1
  4045. */
  4046. function Vec3(x,y,z){
  4047. /**
  4048. * @property x
  4049. * @type {Number}
  4050. */
  4051. this.x = x||0.0;
  4052. /**
  4053. * @property y
  4054. * @type {Number}
  4055. */
  4056. this.y = y||0.0;
  4057. /**
  4058. * @property z
  4059. * @type {Number}
  4060. */
  4061. this.z = z||0.0;
  4062. }
  4063. /**
  4064. * @static
  4065. * @property {Vec3} ZERO
  4066. */
  4067. Vec3.ZERO = new Vec3(0, 0, 0);
  4068. /**
  4069. * @static
  4070. * @property {Vec3} UNIT_X
  4071. */
  4072. Vec3.UNIT_X = new Vec3(1, 0, 0);
  4073. /**
  4074. * @static
  4075. * @property {Vec3} UNIT_Y
  4076. */
  4077. Vec3.UNIT_Y = new Vec3(0, 1, 0);
  4078. /**
  4079. * @static
  4080. * @property {Vec3} UNIT_Z
  4081. */
  4082. Vec3.UNIT_Z = new Vec3(0, 0, 1);
  4083. /**
  4084. * Vector cross product
  4085. * @method cross
  4086. * @param {Vec3} v
  4087. * @param {Vec3} target Optional. Target to save in.
  4088. * @return {Vec3}
  4089. */
  4090. Vec3.prototype.cross = function(v,target){
  4091. var vx=v.x, vy=v.y, vz=v.z, x=this.x, y=this.y, z=this.z;
  4092. target = target || new Vec3();
  4093. target.x = (y * vz) - (z * vy);
  4094. target.y = (z * vx) - (x * vz);
  4095. target.z = (x * vy) - (y * vx);
  4096. return target;
  4097. };
  4098. /**
  4099. * Set the vectors' 3 elements
  4100. * @method set
  4101. * @param {Number} x
  4102. * @param {Number} y
  4103. * @param {Number} z
  4104. * @return Vec3
  4105. */
  4106. Vec3.prototype.set = function(x,y,z){
  4107. this.x = x;
  4108. this.y = y;
  4109. this.z = z;
  4110. return this;
  4111. };
  4112. /**
  4113. * Set all components of the vector to zero.
  4114. * @method setZero
  4115. */
  4116. Vec3.prototype.setZero = function(){
  4117. this.x = this.y = this.z = 0;
  4118. };
  4119. /**
  4120. * Vector addition
  4121. * @method vadd
  4122. * @param {Vec3} v
  4123. * @param {Vec3} target Optional.
  4124. * @return {Vec3}
  4125. */
  4126. Vec3.prototype.vadd = function(v,target){
  4127. if(target){
  4128. target.x = v.x + this.x;
  4129. target.y = v.y + this.y;
  4130. target.z = v.z + this.z;
  4131. } else {
  4132. return new Vec3(this.x + v.x,
  4133. this.y + v.y,
  4134. this.z + v.z);
  4135. }
  4136. };
  4137. /**
  4138. * Vector subtraction
  4139. * @method vsub
  4140. * @param {Vec3} v
  4141. * @param {Vec3} target Optional. Target to save in.
  4142. * @return {Vec3}
  4143. */
  4144. Vec3.prototype.vsub = function(v,target){
  4145. if(target){
  4146. target.x = this.x - v.x;
  4147. target.y = this.y - v.y;
  4148. target.z = this.z - v.z;
  4149. } else {
  4150. return new Vec3(this.x-v.x,
  4151. this.y-v.y,
  4152. this.z-v.z);
  4153. }
  4154. };
  4155. /**
  4156. * Get the cross product matrix a_cross from a vector, such that a x b = a_cross * b = c
  4157. * @method crossmat
  4158. * @see http://www8.cs.umu.se/kurser/TDBD24/VT06/lectures/Lecture6.pdf
  4159. * @return {Mat3}
  4160. */
  4161. Vec3.prototype.crossmat = function(){
  4162. return new Mat3([ 0, -this.z, this.y,
  4163. this.z, 0, -this.x,
  4164. -this.y, this.x, 0]);
  4165. };
  4166. /**
  4167. * Normalize the vector. Note that this changes the values in the vector.
  4168. * @method normalize
  4169. * @return {Number} Returns the norm of the vector
  4170. */
  4171. Vec3.prototype.normalize = function(){
  4172. var x=this.x, y=this.y, z=this.z;
  4173. var n = Math.sqrt(x*x + y*y + z*z);
  4174. if(n>0.0){
  4175. var invN = 1/n;
  4176. this.x *= invN;
  4177. this.y *= invN;
  4178. this.z *= invN;
  4179. } else {
  4180. // Make something up
  4181. this.x = 0;
  4182. this.y = 0;
  4183. this.z = 0;
  4184. }
  4185. return n;
  4186. };
  4187. /**
  4188. * Get the version of this vector that is of length 1.
  4189. * @method unit
  4190. * @param {Vec3} target Optional target to save in
  4191. * @return {Vec3} Returns the unit vector
  4192. */
  4193. Vec3.prototype.unit = function(target){
  4194. target = target || new Vec3();
  4195. var x=this.x, y=this.y, z=this.z;
  4196. var ninv = Math.sqrt(x*x + y*y + z*z);
  4197. if(ninv>0.0){
  4198. ninv = 1.0/ninv;
  4199. target.x = x * ninv;
  4200. target.y = y * ninv;
  4201. target.z = z * ninv;
  4202. } else {
  4203. target.x = 1;
  4204. target.y = 0;
  4205. target.z = 0;
  4206. }
  4207. return target;
  4208. };
  4209. /**
  4210. * Get the length of the vector
  4211. * @method norm
  4212. * @return {Number}
  4213. * @deprecated Use .length() instead
  4214. */
  4215. Vec3.prototype.norm = function(){
  4216. var x=this.x, y=this.y, z=this.z;
  4217. return Math.sqrt(x*x + y*y + z*z);
  4218. };
  4219. /**
  4220. * Get the length of the vector
  4221. * @method length
  4222. * @return {Number}
  4223. */
  4224. Vec3.prototype.length = Vec3.prototype.norm;
  4225. /**
  4226. * Get the squared length of the vector
  4227. * @method norm2
  4228. * @return {Number}
  4229. * @deprecated Use .lengthSquared() instead.
  4230. */
  4231. Vec3.prototype.norm2 = function(){
  4232. return this.dot(this);
  4233. };
  4234. /**
  4235. * Get the squared length of the vector.
  4236. * @method lengthSquared
  4237. * @return {Number}
  4238. */
  4239. Vec3.prototype.lengthSquared = Vec3.prototype.norm2;
  4240. /**
  4241. * Get distance from this point to another point
  4242. * @method distanceTo
  4243. * @param {Vec3} p
  4244. * @return {Number}
  4245. */
  4246. Vec3.prototype.distanceTo = function(p){
  4247. var x=this.x, y=this.y, z=this.z;
  4248. var px=p.x, py=p.y, pz=p.z;
  4249. return Math.sqrt((px-x)*(px-x)+
  4250. (py-y)*(py-y)+
  4251. (pz-z)*(pz-z));
  4252. };
  4253. /**
  4254. * Get squared distance from this point to another point
  4255. * @method distanceSquared
  4256. * @param {Vec3} p
  4257. * @return {Number}
  4258. */
  4259. Vec3.prototype.distanceSquared = function(p){
  4260. var x=this.x, y=this.y, z=this.z;
  4261. var px=p.x, py=p.y, pz=p.z;
  4262. return (px-x)*(px-x) + (py-y)*(py-y) + (pz-z)*(pz-z);
  4263. };
  4264. /**
  4265. * Multiply all the components of the vector with a scalar.
  4266. * @deprecated Use .scale instead
  4267. * @method mult
  4268. * @param {Number} scalar
  4269. * @param {Vec3} target The vector to save the result in.
  4270. * @return {Vec3}
  4271. * @deprecated Use .scale() instead
  4272. */
  4273. Vec3.prototype.mult = function(scalar,target){
  4274. target = target || new Vec3();
  4275. var x = this.x,
  4276. y = this.y,
  4277. z = this.z;
  4278. target.x = scalar * x;
  4279. target.y = scalar * y;
  4280. target.z = scalar * z;
  4281. return target;
  4282. };
  4283. /**
  4284. * Multiply the vector with a scalar.
  4285. * @method scale
  4286. * @param {Number} scalar
  4287. * @param {Vec3} target
  4288. * @return {Vec3}
  4289. */
  4290. Vec3.prototype.scale = Vec3.prototype.mult;
  4291. /**
  4292. * Calculate dot product
  4293. * @method dot
  4294. * @param {Vec3} v
  4295. * @return {Number}
  4296. */
  4297. Vec3.prototype.dot = function(v){
  4298. return this.x * v.x + this.y * v.y + this.z * v.z;
  4299. };
  4300. /**
  4301. * @method isZero
  4302. * @return bool
  4303. */
  4304. Vec3.prototype.isZero = function(){
  4305. return this.x===0 && this.y===0 && this.z===0;
  4306. };
  4307. /**
  4308. * Make the vector point in the opposite direction.
  4309. * @method negate
  4310. * @param {Vec3} target Optional target to save in
  4311. * @return {Vec3}
  4312. */
  4313. Vec3.prototype.negate = function(target){
  4314. target = target || new Vec3();
  4315. target.x = -this.x;
  4316. target.y = -this.y;
  4317. target.z = -this.z;
  4318. return target;
  4319. };
  4320. /**
  4321. * Compute two artificial tangents to the vector
  4322. * @method tangents
  4323. * @param {Vec3} t1 Vector object to save the first tangent in
  4324. * @param {Vec3} t2 Vector object to save the second tangent in
  4325. */
  4326. var Vec3_tangents_n = new Vec3();
  4327. var Vec3_tangents_randVec = new Vec3();
  4328. Vec3.prototype.tangents = function(t1,t2){
  4329. var norm = this.norm();
  4330. if(norm>0.0){
  4331. var n = Vec3_tangents_n;
  4332. var inorm = 1/norm;
  4333. n.set(this.x*inorm,this.y*inorm,this.z*inorm);
  4334. var randVec = Vec3_tangents_randVec;
  4335. if(Math.abs(n.x) < 0.9){
  4336. randVec.set(1,0,0);
  4337. n.cross(randVec,t1);
  4338. } else {
  4339. randVec.set(0,1,0);
  4340. n.cross(randVec,t1);
  4341. }
  4342. n.cross(t1,t2);
  4343. } else {
  4344. // The normal length is zero, make something up
  4345. t1.set(1, 0, 0);
  4346. t2.set(0, 1, 0);
  4347. }
  4348. };
  4349. /**
  4350. * Converts to a more readable format
  4351. * @method toString
  4352. * @return string
  4353. */
  4354. Vec3.prototype.toString = function(){
  4355. return this.x+","+this.y+","+this.z;
  4356. };
  4357. /**
  4358. * Converts to an array
  4359. * @method toArray
  4360. * @return Array
  4361. */
  4362. Vec3.prototype.toArray = function(){
  4363. return [this.x, this.y, this.z];
  4364. };
  4365. /**
  4366. * Copies value of source to this vector.
  4367. * @method copy
  4368. * @param {Vec3} source
  4369. * @return {Vec3} this
  4370. */
  4371. Vec3.prototype.copy = function(source){
  4372. this.x = source.x;
  4373. this.y = source.y;
  4374. this.z = source.z;
  4375. return this;
  4376. };
  4377. /**
  4378. * Do a linear interpolation between two vectors
  4379. * @method lerp
  4380. * @param {Vec3} v
  4381. * @param {Number} t A number between 0 and 1. 0 will make this function return u, and 1 will make it return v. Numbers in between will generate a vector in between them.
  4382. * @param {Vec3} target
  4383. */
  4384. Vec3.prototype.lerp = function(v,t,target){
  4385. var x=this.x, y=this.y, z=this.z;
  4386. target.x = x + (v.x-x)*t;
  4387. target.y = y + (v.y-y)*t;
  4388. target.z = z + (v.z-z)*t;
  4389. };
  4390. /**
  4391. * Check if a vector equals is almost equal to another one.
  4392. * @method almostEquals
  4393. * @param {Vec3} v
  4394. * @param {Number} precision
  4395. * @return bool
  4396. */
  4397. Vec3.prototype.almostEquals = function(v,precision){
  4398. if(precision===undefined){
  4399. precision = 1e-6;
  4400. }
  4401. if( Math.abs(this.x-v.x)>precision ||
  4402. Math.abs(this.y-v.y)>precision ||
  4403. Math.abs(this.z-v.z)>precision){
  4404. return false;
  4405. }
  4406. return true;
  4407. };
  4408. /**
  4409. * Check if a vector is almost zero
  4410. * @method almostZero
  4411. * @param {Number} precision
  4412. */
  4413. Vec3.prototype.almostZero = function(precision){
  4414. if(precision===undefined){
  4415. precision = 1e-6;
  4416. }
  4417. if( Math.abs(this.x)>precision ||
  4418. Math.abs(this.y)>precision ||
  4419. Math.abs(this.z)>precision){
  4420. return false;
  4421. }
  4422. return true;
  4423. };
  4424. var antip_neg = new Vec3();
  4425. /**
  4426. * Check if the vector is anti-parallel to another vector.
  4427. * @method isAntiparallelTo
  4428. * @param {Vec3} v
  4429. * @param {Number} precision Set to zero for exact comparisons
  4430. * @return {Boolean}
  4431. */
  4432. Vec3.prototype.isAntiparallelTo = function(v,precision){
  4433. this.negate(antip_neg);
  4434. return antip_neg.almostEquals(v,precision);
  4435. };
  4436. /**
  4437. * Clone the vector
  4438. * @method clone
  4439. * @return {Vec3}
  4440. */
  4441. Vec3.prototype.clone = function(){
  4442. return new Vec3(this.x, this.y, this.z);
  4443. };
  4444. },{"./Mat3":27}],31:[function(_dereq_,module,exports){
  4445. module.exports = Body;
  4446. var EventTarget = _dereq_('../utils/EventTarget');
  4447. var Shape = _dereq_('../shapes/Shape');
  4448. var Vec3 = _dereq_('../math/Vec3');
  4449. var Mat3 = _dereq_('../math/Mat3');
  4450. var Quaternion = _dereq_('../math/Quaternion');
  4451. var Material = _dereq_('../material/Material');
  4452. var AABB = _dereq_('../collision/AABB');
  4453. var Box = _dereq_('../shapes/Box');
  4454. /**
  4455. * Base class for all body types.
  4456. * @class Body
  4457. * @constructor
  4458. * @extends EventTarget
  4459. * @param {object} [options]
  4460. * @param {Vec3} [options.position]
  4461. * @param {Vec3} [options.velocity]
  4462. * @param {Vec3} [options.angularVelocity]
  4463. * @param {Quaternion} [options.quaternion]
  4464. * @param {number} [options.mass]
  4465. * @param {Material} [options.material]
  4466. * @param {number} [options.type]
  4467. * @param {number} [options.linearDamping=0.01]
  4468. * @param {number} [options.angularDamping=0.01]
  4469. * @param {boolean} [options.allowSleep=true]
  4470. * @param {number} [options.sleepSpeedLimit=0.1]
  4471. * @param {number} [options.sleepTimeLimit=1]
  4472. * @param {number} [options.collisionFilterGroup=1]
  4473. * @param {number} [options.collisionFilterMask=1]
  4474. * @param {boolean} [options.fixedRotation=false]
  4475. * @param {Body} [options.shape]
  4476. * @example
  4477. * var body = new Body({
  4478. * mass: 1
  4479. * });
  4480. * var shape = new Sphere(1);
  4481. * body.addShape(shape);
  4482. * world.add(body);
  4483. */
  4484. function Body(options){
  4485. options = options || {};
  4486. EventTarget.apply(this);
  4487. this.id = Body.idCounter++;
  4488. //miner laya对应ID
  4489. this.layaID;
  4490. //istriger的功能添加
  4491. this.isTrigger = false;
  4492. /**
  4493. * Reference to the world the body is living in
  4494. * @property world
  4495. * @type {World}
  4496. */
  4497. this.world = null;
  4498. /**
  4499. * Callback function that is used BEFORE stepping the system. Use it to apply forces, for example. Inside the function, "this" will refer to this Body object.
  4500. * @property preStep
  4501. * @type {Function}
  4502. * @deprecated Use World events instead
  4503. */
  4504. this.preStep = null;
  4505. /**
  4506. * Callback function that is used AFTER stepping the system. Inside the function, "this" will refer to this Body object.
  4507. * @property postStep
  4508. * @type {Function}
  4509. * @deprecated Use World events instead
  4510. */
  4511. this.postStep = null;
  4512. this.vlambda = new Vec3();
  4513. /**
  4514. * @property {Number} collisionFilterGroup
  4515. */
  4516. this.collisionFilterGroup = typeof(options.collisionFilterGroup) === 'number' ? options.collisionFilterGroup : 1;
  4517. /**
  4518. * @property {Number} collisionFilterMask
  4519. */
  4520. this.collisionFilterMask = typeof(options.collisionFilterMask) === 'number' ? options.collisionFilterMask : 1;
  4521. /**
  4522. * Whether to produce contact forces when in contact with other bodies. Note that contacts will be generated, but they will be disabled.
  4523. * @property {Number} collisionResponse
  4524. */
  4525. this.collisionResponse = true;
  4526. /**
  4527. * @property position
  4528. * @type {Vec3}
  4529. */
  4530. this.position = new Vec3();
  4531. if(options.position){
  4532. this.position.copy(options.position);
  4533. }
  4534. /**
  4535. * @property {Vec3} previousPosition
  4536. */
  4537. this.previousPosition = new Vec3();
  4538. /**
  4539. * Initial position of the body
  4540. * @property initPosition
  4541. * @type {Vec3}
  4542. */
  4543. this.initPosition = new Vec3();
  4544. /**
  4545. * @property velocity
  4546. * @type {Vec3}
  4547. */
  4548. this.velocity = new Vec3();
  4549. if(options.velocity){
  4550. this.velocity.copy(options.velocity);
  4551. }
  4552. /**
  4553. * @property initVelocity
  4554. * @type {Vec3}
  4555. */
  4556. this.initVelocity = new Vec3();
  4557. /**
  4558. * Linear force on the body
  4559. * @property force
  4560. * @type {Vec3}
  4561. */
  4562. this.force = new Vec3();
  4563. var mass = typeof(options.mass) === 'number' ? options.mass : 0;
  4564. /**
  4565. * @property mass
  4566. * @type {Number}
  4567. * @default 0
  4568. */
  4569. this.mass = mass;
  4570. /**
  4571. * @property invMass
  4572. * @type {Number}
  4573. */
  4574. this.invMass = mass > 0 ? 1.0 / mass : 0;
  4575. /**
  4576. * @property material
  4577. * @type {Material}
  4578. */
  4579. this.material = options.material || null;
  4580. /**
  4581. * @property linearDamping
  4582. * @type {Number}
  4583. */
  4584. this.linearDamping = typeof(options.linearDamping) === 'number' ? options.linearDamping : 0.01;
  4585. /**
  4586. * One of: Body.DYNAMIC, Body.STATIC and Body.KINEMATIC.
  4587. * @property type
  4588. * @type {Number}
  4589. */
  4590. this.type = (mass <= 0.0 ? Body.STATIC : Body.DYNAMIC);
  4591. if(typeof(options.type) === typeof(Body.STATIC)){
  4592. this.type = options.type;
  4593. }
  4594. /**
  4595. * If true, the body will automatically fall to sleep.
  4596. * @property allowSleep
  4597. * @type {Boolean}
  4598. * @default true
  4599. */
  4600. this.allowSleep = typeof(options.allowSleep) !== 'undefined' ? options.allowSleep : true;
  4601. /**
  4602. * Current sleep state.
  4603. * @property sleepState
  4604. * @type {Number}
  4605. */
  4606. this.sleepState = 0;
  4607. /**
  4608. * If the speed (the norm of the velocity) is smaller than this value, the body is considered sleepy.
  4609. * @property sleepSpeedLimit
  4610. * @type {Number}
  4611. * @default 0.1
  4612. */
  4613. this.sleepSpeedLimit = typeof(options.sleepSpeedLimit) !== 'undefined' ? options.sleepSpeedLimit : 0.1;
  4614. /**
  4615. * If the body has been sleepy for this sleepTimeLimit seconds, it is considered sleeping.
  4616. * @property sleepTimeLimit
  4617. * @type {Number}
  4618. * @default 1
  4619. */
  4620. this.sleepTimeLimit = typeof(options.sleepTimeLimit) !== 'undefined' ? options.sleepTimeLimit : 1;
  4621. this.timeLastSleepy = 0;
  4622. this._wakeUpAfterNarrowphase = false;
  4623. /**
  4624. * Rotational force on the body, around center of mass
  4625. * @property {Vec3} torque
  4626. */
  4627. this.torque = new Vec3();
  4628. /**
  4629. * Orientation of the body
  4630. * @property quaternion
  4631. * @type {Quaternion}
  4632. */
  4633. this.quaternion = new Quaternion();
  4634. if(options.quaternion){
  4635. this.quaternion.copy(options.quaternion);
  4636. }
  4637. /**
  4638. * @property initQuaternion
  4639. * @type {Quaternion}
  4640. */
  4641. this.initQuaternion = new Quaternion();
  4642. /**
  4643. * @property angularVelocity
  4644. * @type {Vec3}
  4645. */
  4646. this.angularVelocity = new Vec3();
  4647. if(options.angularVelocity){
  4648. this.angularVelocity.copy(options.angularVelocity);
  4649. }
  4650. /**
  4651. * @property initAngularVelocity
  4652. * @type {Vec3}
  4653. */
  4654. this.initAngularVelocity = new Vec3();
  4655. this.interpolatedPosition = new Vec3();
  4656. this.interpolatedQuaternion = new Quaternion();
  4657. /**
  4658. * @property shapes
  4659. * @type {array}
  4660. */
  4661. this.shapes = [];
  4662. /**
  4663. * @property shapeOffsets
  4664. * @type {array}
  4665. */
  4666. this.shapeOffsets = [];
  4667. /**
  4668. * @property shapeOrientations
  4669. * @type {array}
  4670. */
  4671. this.shapeOrientations = [];
  4672. /**
  4673. * @property inertia
  4674. * @type {Vec3}
  4675. */
  4676. this.inertia = new Vec3();
  4677. /**
  4678. * @property {Vec3} invInertia
  4679. */
  4680. this.invInertia = new Vec3();
  4681. /**
  4682. * @property {Mat3} invInertiaWorld
  4683. */
  4684. this.invInertiaWorld = new Mat3();
  4685. this.invMassSolve = 0;
  4686. /**
  4687. * @property {Vec3} invInertiaSolve
  4688. */
  4689. this.invInertiaSolve = new Vec3();
  4690. /**
  4691. * @property {Mat3} invInertiaWorldSolve
  4692. */
  4693. this.invInertiaWorldSolve = new Mat3();
  4694. /**
  4695. * Set to true if you don't want the body to rotate. Make sure to run .updateMassProperties() after changing this.
  4696. * @property {Boolean} fixedRotation
  4697. * @default false
  4698. */
  4699. this.fixedRotation = typeof(options.fixedRotation) !== "undefined" ? options.fixedRotation : false;
  4700. /**
  4701. * @property {Number} angularDamping
  4702. */
  4703. this.angularDamping = typeof(options.angularDamping) !== 'undefined' ? options.angularDamping : 0.01;
  4704. /**
  4705. * @property aabb
  4706. * @type {AABB}
  4707. */
  4708. this.aabb = new AABB();
  4709. /**
  4710. * Indicates if the AABB needs to be updated before use.
  4711. * @property aabbNeedsUpdate
  4712. * @type {Boolean}
  4713. */
  4714. this.aabbNeedsUpdate = true;
  4715. this.wlambda = new Vec3();
  4716. if(options.shape){
  4717. this.addShape(options.shape);
  4718. }
  4719. this.updateMassProperties();
  4720. }
  4721. Body.prototype = new EventTarget();
  4722. Body.prototype.constructor = Body;
  4723. /**
  4724. * A dynamic body is fully simulated. Can be moved manually by the user, but normally they move according to forces. A dynamic body can collide with all body types. A dynamic body always has finite, non-zero mass.
  4725. * @static
  4726. * @property DYNAMIC
  4727. * @type {Number}
  4728. */
  4729. Body.DYNAMIC = 1;
  4730. /**
  4731. * A static body does not move during simulation and behaves as if it has infinite mass. Static bodies can be moved manually by setting the position of the body. The velocity of a static body is always zero. Static bodies do not collide with other static or kinematic bodies.
  4732. * @static
  4733. * @property STATIC
  4734. * @type {Number}
  4735. */
  4736. Body.STATIC = 2;
  4737. /**
  4738. * A kinematic body moves under simulation according to its velocity. They do not respond to forces. They can be moved manually, but normally a kinematic body is moved by setting its velocity. A kinematic body behaves as if it has infinite mass. Kinematic bodies do not collide with other static or kinematic bodies.
  4739. * @static
  4740. * @property KINEMATIC
  4741. * @type {Number}
  4742. */
  4743. Body.KINEMATIC = 4;
  4744. /**
  4745. * @static
  4746. * @property AWAKE
  4747. * @type {number}
  4748. */
  4749. Body.AWAKE = 0;
  4750. /**
  4751. * @static
  4752. * @property SLEEPY
  4753. * @type {number}
  4754. */
  4755. Body.SLEEPY = 1;
  4756. /**
  4757. * @static
  4758. * @property SLEEPING
  4759. * @type {number}
  4760. */
  4761. Body.SLEEPING = 2;
  4762. Body.idCounter = 0;
  4763. /**
  4764. * Wake the body up.
  4765. * @method wakeUp
  4766. */
  4767. Body.prototype.wakeUp = function(){
  4768. var s = this.sleepState;
  4769. this.sleepState = 0;
  4770. if(s === Body.SLEEPING){
  4771. this.dispatchEvent({type:"wakeup"});
  4772. }
  4773. };
  4774. /**
  4775. * Force body sleep
  4776. * @method sleep
  4777. */
  4778. Body.prototype.sleep = function(){
  4779. this.sleepState = Body.SLEEPING;
  4780. this.velocity.set(0,0,0);
  4781. this.angularVelocity.set(0,0,0);
  4782. };
  4783. Body.sleepyEvent = {
  4784. type: "sleepy"
  4785. };
  4786. Body.sleepEvent = {
  4787. type: "sleep"
  4788. };
  4789. /**
  4790. * Called every timestep to update internal sleep timer and change sleep state if needed.
  4791. * @method sleepTick
  4792. * @param {Number} time The world time in seconds
  4793. */
  4794. Body.prototype.sleepTick = function(time){
  4795. if(this.allowSleep){
  4796. var sleepState = this.sleepState;
  4797. var speedSquared = this.velocity.norm2() + this.angularVelocity.norm2();
  4798. var speedLimitSquared = Math.pow(this.sleepSpeedLimit,2);
  4799. if(sleepState===Body.AWAKE && speedSquared < speedLimitSquared){
  4800. this.sleepState = Body.SLEEPY; // Sleepy
  4801. this.timeLastSleepy = time;
  4802. this.dispatchEvent(Body.sleepyEvent);
  4803. } else if(sleepState===Body.SLEEPY && speedSquared > speedLimitSquared){
  4804. this.wakeUp(); // Wake up
  4805. } else if(sleepState===Body.SLEEPY && (time - this.timeLastSleepy ) > this.sleepTimeLimit){
  4806. this.sleep(); // Sleeping
  4807. this.dispatchEvent(Body.sleepEvent);
  4808. }
  4809. }
  4810. };
  4811. /**
  4812. * If the body is sleeping, it should be immovable / have infinite mass during solve. We solve it by having a separate "solve mass".
  4813. * @method updateSolveMassProperties
  4814. */
  4815. Body.prototype.updateSolveMassProperties = function(){
  4816. if(this.sleepState === Body.SLEEPING || this.type === Body.KINEMATIC){
  4817. this.invMassSolve = 0;
  4818. this.invInertiaSolve.setZero();
  4819. this.invInertiaWorldSolve.setZero();
  4820. } else {
  4821. this.invMassSolve = this.invMass;
  4822. this.invInertiaSolve.copy(this.invInertia);
  4823. this.invInertiaWorldSolve.copy(this.invInertiaWorld);
  4824. }
  4825. };
  4826. /**
  4827. * Convert a world point to local body frame.
  4828. * @method pointToLocalFrame
  4829. * @param {Vec3} worldPoint
  4830. * @param {Vec3} result
  4831. * @return {Vec3}
  4832. */
  4833. Body.prototype.pointToLocalFrame = function(worldPoint,result){
  4834. var result = result || new Vec3();
  4835. worldPoint.vsub(this.position,result);
  4836. this.quaternion.conjugate().vmult(result,result);
  4837. return result;
  4838. };
  4839. /**
  4840. * Convert a world vector to local body frame.
  4841. * @method vectorToLocalFrame
  4842. * @param {Vec3} worldPoint
  4843. * @param {Vec3} result
  4844. * @return {Vec3}
  4845. */
  4846. Body.prototype.vectorToLocalFrame = function(worldVector, result){
  4847. var result = result || new Vec3();
  4848. this.quaternion.conjugate().vmult(worldVector,result);
  4849. return result;
  4850. };
  4851. /**
  4852. * Convert a local body point to world frame.
  4853. * @method pointToWorldFrame
  4854. * @param {Vec3} localPoint
  4855. * @param {Vec3} result
  4856. * @return {Vec3}
  4857. */
  4858. Body.prototype.pointToWorldFrame = function(localPoint,result){
  4859. var result = result || new Vec3();
  4860. this.quaternion.vmult(localPoint,result);
  4861. result.vadd(this.position,result);
  4862. return result;
  4863. };
  4864. /**
  4865. * Convert a local body point to world frame.
  4866. * @method vectorToWorldFrame
  4867. * @param {Vec3} localVector
  4868. * @param {Vec3} result
  4869. * @return {Vec3}
  4870. */
  4871. Body.prototype.vectorToWorldFrame = function(localVector, result){
  4872. var result = result || new Vec3();
  4873. this.quaternion.vmult(localVector, result);
  4874. return result;
  4875. };
  4876. var tmpVec = new Vec3();
  4877. var tmpQuat = new Quaternion();
  4878. /**
  4879. * Add a shape to the body with a local offset and orientation.
  4880. * @method addShape
  4881. * @param {Shape} shape
  4882. * @param {Vec3} offset
  4883. * @param {Quaternion} quaternion
  4884. * @return {Body} The body object, for chainability.
  4885. */
  4886. Body.prototype.addShape = function(shape, _offset, _orientation){
  4887. var offset = new Vec3();
  4888. var orientation = new Quaternion();
  4889. if(_offset){
  4890. offset.copy(_offset);
  4891. }
  4892. if(_orientation){
  4893. orientation.copy(_orientation);
  4894. }
  4895. this.shapes.push(shape);
  4896. this.shapeOffsets.push(offset);
  4897. this.shapeOrientations.push(orientation);
  4898. this.updateMassProperties();
  4899. this.updateBoundingRadius();
  4900. this.aabbNeedsUpdate = true;
  4901. return this;
  4902. };
  4903. /**
  4904. * Update the bounding radius of the body. Should be done if any of the shapes are changed.
  4905. * @method updateBoundingRadius
  4906. */
  4907. Body.prototype.updateBoundingRadius = function(){
  4908. var shapes = this.shapes,
  4909. shapeOffsets = this.shapeOffsets,
  4910. N = shapes.length,
  4911. radius = 0;
  4912. for(var i=0; i!==N; i++){
  4913. var shape = shapes[i];
  4914. shape.updateBoundingSphereRadius();
  4915. var offset = shapeOffsets[i].norm(),
  4916. r = shape.boundingSphereRadius;
  4917. if(offset + r > radius){
  4918. radius = offset + r;
  4919. }
  4920. }
  4921. this.boundingRadius = radius;
  4922. };
  4923. var computeAABB_shapeAABB = new AABB();
  4924. /**
  4925. * Updates the .aabb
  4926. * @method computeAABB
  4927. * @todo rename to updateAABB()
  4928. */
  4929. Body.prototype.computeAABB = function(){
  4930. var shapes = this.shapes,
  4931. shapeOffsets = this.shapeOffsets,
  4932. shapeOrientations = this.shapeOrientations,
  4933. N = shapes.length,
  4934. offset = tmpVec,
  4935. orientation = tmpQuat,
  4936. bodyQuat = this.quaternion,
  4937. aabb = this.aabb,
  4938. shapeAABB = computeAABB_shapeAABB;
  4939. for(var i=0; i!==N; i++){
  4940. var shape = shapes[i];
  4941. // Get shape world quaternion
  4942. shapeOrientations[i].mult(bodyQuat, orientation);
  4943. // Get shape world position
  4944. orientation.vmult(shapeOffsets[i], offset);
  4945. offset.vadd(this.position, offset);
  4946. // vec2.rotate(offset, shapeOffsets[i], bodyAngle);
  4947. // vec2.add(offset, offset, this.position);
  4948. // Get shape AABB
  4949. shape.calculateWorldAABB(offset, orientation, shapeAABB.lowerBound, shapeAABB.upperBound);
  4950. if(i === 0){
  4951. aabb.copy(shapeAABB);
  4952. } else {
  4953. aabb.extend(shapeAABB);
  4954. }
  4955. }
  4956. this.aabbNeedsUpdate = false;
  4957. };
  4958. var uiw_m1 = new Mat3(),
  4959. uiw_m2 = new Mat3(),
  4960. uiw_m3 = new Mat3();
  4961. /**
  4962. * Update .inertiaWorld and .invInertiaWorld
  4963. * @method updateInertiaWorld
  4964. */
  4965. Body.prototype.updateInertiaWorld = function(force){
  4966. var I = this.invInertia;
  4967. if (I.x === I.y && I.y === I.z && !force) {
  4968. // If inertia M = s*I, where I is identity and s a scalar, then
  4969. // R*M*R' = R*(s*I)*R' = s*R*I*R' = s*R*R' = s*I = M
  4970. // where R is the rotation matrix.
  4971. // In other words, we don't have to transform the inertia if all
  4972. // inertia diagonal entries are equal.
  4973. } else {
  4974. var m1 = uiw_m1,
  4975. m2 = uiw_m2,
  4976. m3 = uiw_m3;
  4977. m1.setRotationFromQuaternion(this.quaternion);
  4978. m1.transpose(m2);
  4979. m1.scale(I,m1);
  4980. m1.mmult(m2,this.invInertiaWorld);
  4981. //m3.getTrace(this.invInertiaWorld);
  4982. }
  4983. /*
  4984. this.quaternion.vmult(this.inertia,this.inertiaWorld);
  4985. this.quaternion.vmult(this.invInertia,this.invInertiaWorld);
  4986. */
  4987. };
  4988. /**
  4989. * Apply force to a world point. This could for example be a point on the Body surface. Applying force this way will add to Body.force and Body.torque.
  4990. * @method applyForce
  4991. * @param {Vec3} force The amount of force to add.
  4992. * @param {Vec3} worldPoint A world point to apply the force on.
  4993. */
  4994. var Body_applyForce_r = new Vec3();
  4995. var Body_applyForce_rotForce = new Vec3();
  4996. Body.prototype.applyForce = function(force,worldPoint){
  4997. if(this.type !== Body.DYNAMIC){
  4998. return;
  4999. }
  5000. // Compute point position relative to the body center
  5001. var r = Body_applyForce_r;
  5002. worldPoint.vsub(this.position,r);
  5003. // Compute produced rotational force
  5004. var rotForce = Body_applyForce_rotForce;
  5005. r.cross(force,rotForce);
  5006. // Add linear force
  5007. this.force.vadd(force,this.force);
  5008. // Add rotational force
  5009. this.torque.vadd(rotForce,this.torque);
  5010. };
  5011. /**
  5012. * Apply force to a local point in the body.
  5013. * @method applyLocalForce
  5014. * @param {Vec3} force The force vector to apply, defined locally in the body frame.
  5015. * @param {Vec3} localPoint A local point in the body to apply the force on.
  5016. */
  5017. var Body_applyLocalForce_worldForce = new Vec3();
  5018. var Body_applyLocalForce_worldPoint = new Vec3();
  5019. Body.prototype.applyLocalForce = function(localForce, localPoint){
  5020. if(this.type !== Body.DYNAMIC){
  5021. return;
  5022. }
  5023. var worldForce = Body_applyLocalForce_worldForce;
  5024. var worldPoint = Body_applyLocalForce_worldPoint;
  5025. // Transform the force vector to world space
  5026. this.vectorToWorldFrame(localForce, worldForce);
  5027. this.pointToWorldFrame(localPoint, worldPoint);
  5028. this.applyForce(worldForce, worldPoint);
  5029. };
  5030. /**
  5031. * Apply impulse to a world point. This could for example be a point on the Body surface. An impulse is a force added to a body during a short period of time (impulse = force * time). Impulses will be added to Body.velocity and Body.angularVelocity.
  5032. * @method applyImpulse
  5033. * @param {Vec3} impulse The amount of impulse to add.
  5034. * @param {Vec3} worldPoint A world point to apply the force on.
  5035. */
  5036. var Body_applyImpulse_r = new Vec3();
  5037. var Body_applyImpulse_velo = new Vec3();
  5038. var Body_applyImpulse_rotVelo = new Vec3();
  5039. Body.prototype.applyImpulse = function(impulse, worldPoint){
  5040. if(this.type !== Body.DYNAMIC){
  5041. return;
  5042. }
  5043. // Compute point position relative to the body center
  5044. var r = Body_applyImpulse_r;
  5045. worldPoint.vsub(this.position,r);
  5046. // Compute produced central impulse velocity
  5047. var velo = Body_applyImpulse_velo;
  5048. velo.copy(impulse);
  5049. velo.mult(this.invMass,velo);
  5050. // Add linear impulse
  5051. this.velocity.vadd(velo, this.velocity);
  5052. // Compute produced rotational impulse velocity
  5053. var rotVelo = Body_applyImpulse_rotVelo;
  5054. r.cross(impulse,rotVelo);
  5055. /*
  5056. rotVelo.x *= this.invInertia.x;
  5057. rotVelo.y *= this.invInertia.y;
  5058. rotVelo.z *= this.invInertia.z;
  5059. */
  5060. this.invInertiaWorld.vmult(rotVelo,rotVelo);
  5061. // Add rotational Impulse
  5062. this.angularVelocity.vadd(rotVelo, this.angularVelocity);
  5063. };
  5064. /**
  5065. * Apply locally-defined impulse to a local point in the body.
  5066. * @method applyLocalImpulse
  5067. * @param {Vec3} force The force vector to apply, defined locally in the body frame.
  5068. * @param {Vec3} localPoint A local point in the body to apply the force on.
  5069. */
  5070. var Body_applyLocalImpulse_worldImpulse = new Vec3();
  5071. var Body_applyLocalImpulse_worldPoint = new Vec3();
  5072. Body.prototype.applyLocalImpulse = function(localImpulse, localPoint){
  5073. if(this.type !== Body.DYNAMIC){
  5074. return;
  5075. }
  5076. var worldImpulse = Body_applyLocalImpulse_worldImpulse;
  5077. var worldPoint = Body_applyLocalImpulse_worldPoint;
  5078. // Transform the force vector to world space
  5079. this.vectorToWorldFrame(localImpulse, worldImpulse);
  5080. this.pointToWorldFrame(localPoint, worldPoint);
  5081. this.applyImpulse(worldImpulse, worldPoint);
  5082. };
  5083. var Body_updateMassProperties_halfExtents = new Vec3();
  5084. /**
  5085. * Should be called whenever you change the body shape or mass.
  5086. * @method updateMassProperties
  5087. */
  5088. Body.prototype.updateMassProperties = function(){
  5089. var halfExtents = Body_updateMassProperties_halfExtents;
  5090. this.invMass = this.mass > 0 ? 1.0 / this.mass : 0;
  5091. var I = this.inertia;
  5092. var fixed = this.fixedRotation;
  5093. // Approximate with AABB box
  5094. this.computeAABB();
  5095. halfExtents.set(
  5096. (this.aabb.upperBound.x-this.aabb.lowerBound.x) / 2,
  5097. (this.aabb.upperBound.y-this.aabb.lowerBound.y) / 2,
  5098. (this.aabb.upperBound.z-this.aabb.lowerBound.z) / 2
  5099. );
  5100. Box.calculateInertia(halfExtents, this.mass, I);
  5101. this.invInertia.set(
  5102. I.x > 0 && !fixed ? 1.0 / I.x : 0,
  5103. I.y > 0 && !fixed ? 1.0 / I.y : 0,
  5104. I.z > 0 && !fixed ? 1.0 / I.z : 0
  5105. );
  5106. this.updateInertiaWorld(true);
  5107. };
  5108. /**
  5109. * Get world velocity of a point in the body.
  5110. * @method getVelocityAtWorldPoint
  5111. * @param {Vec3} worldPoint
  5112. * @param {Vec3} result
  5113. * @return {Vec3} The result vector.
  5114. */
  5115. Body.prototype.getVelocityAtWorldPoint = function(worldPoint, result){
  5116. var r = new Vec3();
  5117. worldPoint.vsub(this.position, r);
  5118. this.angularVelocity.cross(r, result);
  5119. this.velocity.vadd(result, result);
  5120. return result;
  5121. };
  5122. },{"../collision/AABB":3,"../material/Material":25,"../math/Mat3":27,"../math/Quaternion":28,"../math/Vec3":30,"../shapes/Box":37,"../shapes/Shape":43,"../utils/EventTarget":49}],32:[function(_dereq_,module,exports){
  5123. var Body = _dereq_('./Body');
  5124. var Vec3 = _dereq_('../math/Vec3');
  5125. var Quaternion = _dereq_('../math/Quaternion');
  5126. var RaycastResult = _dereq_('../collision/RaycastResult');
  5127. var Ray = _dereq_('../collision/Ray');
  5128. var WheelInfo = _dereq_('../objects/WheelInfo');
  5129. module.exports = RaycastVehicle;
  5130. /**
  5131. * Vehicle helper class that casts rays from the wheel positions towards the ground and applies forces.
  5132. * @class RaycastVehicle
  5133. * @constructor
  5134. * @param {object} [options]
  5135. * @param {Body} [options.chassisBody] The car chassis body.
  5136. * @param {integer} [options.indexRightAxis] Axis to use for right. x=0, y=1, z=2
  5137. * @param {integer} [options.indexLeftAxis]
  5138. * @param {integer} [options.indexUpAxis]
  5139. */
  5140. function RaycastVehicle(options){
  5141. /**
  5142. * @property {Body} chassisBody
  5143. */
  5144. this.chassisBody = options.chassisBody;
  5145. /**
  5146. * An array of WheelInfo objects.
  5147. * @property {array} wheelInfos
  5148. */
  5149. this.wheelInfos = [];
  5150. /**
  5151. * Will be set to true if the car is sliding.
  5152. * @property {boolean} sliding
  5153. */
  5154. this.sliding = false;
  5155. /**
  5156. * @property {World} world
  5157. */
  5158. this.world = null;
  5159. /**
  5160. * Index of the right axis, 0=x, 1=y, 2=z
  5161. * @property {integer} indexRightAxis
  5162. * @default 1
  5163. */
  5164. this.indexRightAxis = typeof(options.indexRightAxis) !== 'undefined' ? options.indexRightAxis : 1;
  5165. /**
  5166. * Index of the forward axis, 0=x, 1=y, 2=z
  5167. * @property {integer} indexForwardAxis
  5168. * @default 0
  5169. */
  5170. this.indexForwardAxis = typeof(options.indexForwardAxis) !== 'undefined' ? options.indexForwardAxis : 0;
  5171. /**
  5172. * Index of the up axis, 0=x, 1=y, 2=z
  5173. * @property {integer} indexUpAxis
  5174. * @default 2
  5175. */
  5176. this.indexUpAxis = typeof(options.indexUpAxis) !== 'undefined' ? options.indexUpAxis : 2;
  5177. }
  5178. var tmpVec1 = new Vec3();
  5179. var tmpVec2 = new Vec3();
  5180. var tmpVec3 = new Vec3();
  5181. var tmpVec4 = new Vec3();
  5182. var tmpVec5 = new Vec3();
  5183. var tmpVec6 = new Vec3();
  5184. var tmpRay = new Ray();
  5185. /**
  5186. * Add a wheel. For information about the options, see WheelInfo.
  5187. * @method addWheel
  5188. * @param {object} [options]
  5189. */
  5190. RaycastVehicle.prototype.addWheel = function(options){
  5191. options = options || {};
  5192. var info = new WheelInfo(options);
  5193. var index = this.wheelInfos.length;
  5194. this.wheelInfos.push(info);
  5195. return index;
  5196. };
  5197. /**
  5198. * Set the steering value of a wheel.
  5199. * @method setSteeringValue
  5200. * @param {number} value
  5201. * @param {integer} wheelIndex
  5202. */
  5203. RaycastVehicle.prototype.setSteeringValue = function(value, wheelIndex){
  5204. var wheel = this.wheelInfos[wheelIndex];
  5205. wheel.steering = value;
  5206. };
  5207. var torque = new Vec3();
  5208. /**
  5209. * Set the wheel force to apply on one of the wheels each time step
  5210. * @method applyEngineForce
  5211. * @param {number} value
  5212. * @param {integer} wheelIndex
  5213. */
  5214. RaycastVehicle.prototype.applyEngineForce = function(value, wheelIndex){
  5215. this.wheelInfos[wheelIndex].engineForce = value;
  5216. };
  5217. /**
  5218. * Set the braking force of a wheel
  5219. * @method setBrake
  5220. * @param {number} brake
  5221. * @param {integer} wheelIndex
  5222. */
  5223. RaycastVehicle.prototype.setBrake = function(brake, wheelIndex){
  5224. this.wheelInfos[wheelIndex].brake = brake;
  5225. };
  5226. /**
  5227. * Add the vehicle including its constraints to the world.
  5228. * @method addToWorld
  5229. * @param {World} world
  5230. */
  5231. RaycastVehicle.prototype.addToWorld = function(world){
  5232. var constraints = this.constraints;
  5233. world.add(this.chassisBody);
  5234. var that = this;
  5235. this.preStepCallback = function(){
  5236. that.updateVehicle(world.dt);
  5237. };
  5238. world.addEventListener('preStep', this.preStepCallback);
  5239. this.world = world;
  5240. };
  5241. /**
  5242. * Get one of the wheel axles, world-oriented.
  5243. * @private
  5244. * @method getVehicleAxisWorld
  5245. * @param {integer} axisIndex
  5246. * @param {Vec3} result
  5247. */
  5248. RaycastVehicle.prototype.getVehicleAxisWorld = function(axisIndex, result){
  5249. result.set(
  5250. axisIndex === 0 ? 1 : 0,
  5251. axisIndex === 1 ? 1 : 0,
  5252. axisIndex === 2 ? 1 : 0
  5253. );
  5254. this.chassisBody.vectorToWorldFrame(result, result);
  5255. };
  5256. RaycastVehicle.prototype.updateVehicle = function(timeStep){
  5257. var wheelInfos = this.wheelInfos;
  5258. var numWheels = wheelInfos.length;
  5259. var chassisBody = this.chassisBody;
  5260. for (var i = 0; i < numWheels; i++) {
  5261. this.updateWheelTransform(i);
  5262. }
  5263. this.currentVehicleSpeedKmHour = 3.6 * chassisBody.velocity.norm();
  5264. var forwardWorld = new Vec3();
  5265. this.getVehicleAxisWorld(this.indexForwardAxis, forwardWorld);
  5266. if (forwardWorld.dot(chassisBody.velocity) < 0){
  5267. this.currentVehicleSpeedKmHour *= -1;
  5268. }
  5269. // simulate suspension
  5270. for (var i = 0; i < numWheels; i++) {
  5271. this.castRay(wheelInfos[i]);
  5272. }
  5273. this.updateSuspension(timeStep);
  5274. var impulse = new Vec3();
  5275. var relpos = new Vec3();
  5276. for (var i = 0; i < numWheels; i++) {
  5277. //apply suspension force
  5278. var wheel = wheelInfos[i];
  5279. var suspensionForce = wheel.suspensionForce;
  5280. if (suspensionForce > wheel.maxSuspensionForce) {
  5281. suspensionForce = wheel.maxSuspensionForce;
  5282. }
  5283. wheel.raycastResult.hitNormalWorld.scale(suspensionForce * timeStep, impulse);
  5284. wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, relpos);
  5285. chassisBody.applyImpulse(impulse, wheel.raycastResult.hitPointWorld/*relpos*/);
  5286. }
  5287. this.updateFriction(timeStep);
  5288. var hitNormalWorldScaledWithProj = new Vec3();
  5289. var fwd = new Vec3();
  5290. var vel = new Vec3();
  5291. for (i = 0; i < numWheels; i++) {
  5292. var wheel = wheelInfos[i];
  5293. //var relpos = new Vec3();
  5294. //wheel.chassisConnectionPointWorld.vsub(chassisBody.position, relpos);
  5295. chassisBody.getVelocityAtWorldPoint(wheel.chassisConnectionPointWorld, vel);
  5296. // Hack to get the rotation in the correct direction
  5297. var m = 1;
  5298. switch(this.indexUpAxis){
  5299. case 1:
  5300. m = -1;
  5301. break;
  5302. }
  5303. if (wheel.isInContact) {
  5304. this.getVehicleAxisWorld(this.indexForwardAxis, fwd);
  5305. var proj = fwd.dot(wheel.raycastResult.hitNormalWorld);
  5306. wheel.raycastResult.hitNormalWorld.scale(proj, hitNormalWorldScaledWithProj);
  5307. fwd.vsub(hitNormalWorldScaledWithProj, fwd);
  5308. var proj2 = fwd.dot(vel);
  5309. wheel.deltaRotation = m * proj2 * timeStep / wheel.radius;
  5310. }
  5311. if((wheel.sliding || !wheel.isInContact) && wheel.engineForce !== 0 && wheel.useCustomSlidingRotationalSpeed){
  5312. // Apply custom rotation when accelerating and sliding
  5313. wheel.deltaRotation = (wheel.engineForce > 0 ? 1 : -1) * wheel.customSlidingRotationalSpeed * timeStep;
  5314. }
  5315. // Lock wheels
  5316. if(Math.abs(wheel.brake) > Math.abs(wheel.engineForce)){
  5317. wheel.deltaRotation = 0;
  5318. }
  5319. wheel.rotation += wheel.deltaRotation; // Use the old value
  5320. wheel.deltaRotation *= 0.99; // damping of rotation when not in contact
  5321. }
  5322. };
  5323. RaycastVehicle.prototype.updateSuspension = function(deltaTime) {
  5324. var chassisBody = this.chassisBody;
  5325. var chassisMass = chassisBody.mass;
  5326. var wheelInfos = this.wheelInfos;
  5327. var numWheels = wheelInfos.length;
  5328. for (var w_it = 0; w_it < numWheels; w_it++){
  5329. var wheel = wheelInfos[w_it];
  5330. if (wheel.isInContact){
  5331. var force;
  5332. // Spring
  5333. var susp_length = wheel.suspensionRestLength;
  5334. var current_length = wheel.suspensionLength;
  5335. var length_diff = (susp_length - current_length);
  5336. force = wheel.suspensionStiffness * length_diff * wheel.clippedInvContactDotSuspension;
  5337. // Damper
  5338. var projected_rel_vel = wheel.suspensionRelativeVelocity;
  5339. var susp_damping;
  5340. if (projected_rel_vel < 0) {
  5341. susp_damping = wheel.dampingCompression;
  5342. } else {
  5343. susp_damping = wheel.dampingRelaxation;
  5344. }
  5345. force -= susp_damping * projected_rel_vel;
  5346. wheel.suspensionForce = force * chassisMass;
  5347. if (wheel.suspensionForce < 0) {
  5348. wheel.suspensionForce = 0;
  5349. }
  5350. } else {
  5351. wheel.suspensionForce = 0;
  5352. }
  5353. }
  5354. };
  5355. /**
  5356. * Remove the vehicle including its constraints from the world.
  5357. * @method removeFromWorld
  5358. * @param {World} world
  5359. */
  5360. RaycastVehicle.prototype.removeFromWorld = function(world){
  5361. var constraints = this.constraints;
  5362. world.remove(this.chassisBody);
  5363. world.removeEventListener('preStep', this.preStepCallback);
  5364. this.world = null;
  5365. };
  5366. var castRay_rayvector = new Vec3();
  5367. var castRay_target = new Vec3();
  5368. RaycastVehicle.prototype.castRay = function(wheel) {
  5369. var rayvector = castRay_rayvector;
  5370. var target = castRay_target;
  5371. this.updateWheelTransformWorld(wheel);
  5372. var chassisBody = this.chassisBody;
  5373. var depth = -1;
  5374. var raylen = wheel.suspensionRestLength + wheel.radius;
  5375. wheel.directionWorld.scale(raylen, rayvector);
  5376. var source = wheel.chassisConnectionPointWorld;
  5377. source.vadd(rayvector, target);
  5378. var raycastResult = wheel.raycastResult;
  5379. var param = 0;
  5380. raycastResult.reset();
  5381. // Turn off ray collision with the chassis temporarily
  5382. var oldState = chassisBody.collisionResponse;
  5383. chassisBody.collisionResponse = false;
  5384. // Cast ray against world
  5385. this.world.rayTest(source, target, raycastResult);
  5386. chassisBody.collisionResponse = oldState;
  5387. var object = raycastResult.body;
  5388. wheel.raycastResult.groundObject = 0;
  5389. if (object) {
  5390. depth = raycastResult.distance;
  5391. wheel.raycastResult.hitNormalWorld = raycastResult.hitNormalWorld;
  5392. wheel.isInContact = true;
  5393. var hitDistance = raycastResult.distance;
  5394. wheel.suspensionLength = hitDistance - wheel.radius;
  5395. // clamp on max suspension travel
  5396. var minSuspensionLength = wheel.suspensionRestLength - wheel.maxSuspensionTravel;
  5397. var maxSuspensionLength = wheel.suspensionRestLength + wheel.maxSuspensionTravel;
  5398. if (wheel.suspensionLength < minSuspensionLength) {
  5399. wheel.suspensionLength = minSuspensionLength;
  5400. }
  5401. if (wheel.suspensionLength > maxSuspensionLength) {
  5402. wheel.suspensionLength = maxSuspensionLength;
  5403. wheel.raycastResult.reset();
  5404. }
  5405. var denominator = wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld);
  5406. var chassis_velocity_at_contactPoint = new Vec3();
  5407. chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld, chassis_velocity_at_contactPoint);
  5408. var projVel = wheel.raycastResult.hitNormalWorld.dot( chassis_velocity_at_contactPoint );
  5409. if (denominator >= -0.1) {
  5410. wheel.suspensionRelativeVelocity = 0;
  5411. wheel.clippedInvContactDotSuspension = 1 / 0.1;
  5412. } else {
  5413. var inv = -1 / denominator;
  5414. wheel.suspensionRelativeVelocity = projVel * inv;
  5415. wheel.clippedInvContactDotSuspension = inv;
  5416. }
  5417. } else {
  5418. //put wheel info as in rest position
  5419. wheel.suspensionLength = wheel.suspensionRestLength + 0 * wheel.maxSuspensionTravel;
  5420. wheel.suspensionRelativeVelocity = 0.0;
  5421. wheel.directionWorld.scale(-1, wheel.raycastResult.hitNormalWorld);
  5422. wheel.clippedInvContactDotSuspension = 1.0;
  5423. }
  5424. return depth;
  5425. };
  5426. RaycastVehicle.prototype.updateWheelTransformWorld = function(wheel){
  5427. wheel.isInContact = false;
  5428. var chassisBody = this.chassisBody;
  5429. chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal, wheel.chassisConnectionPointWorld);
  5430. chassisBody.vectorToWorldFrame(wheel.directionLocal, wheel.directionWorld);
  5431. chassisBody.vectorToWorldFrame(wheel.axleLocal, wheel.axleWorld);
  5432. };
  5433. /**
  5434. * Update one of the wheel transform.
  5435. * Note when rendering wheels: during each step, wheel transforms are updated BEFORE the chassis; ie. their position becomes invalid after the step. Thus when you render wheels, you must update wheel transforms before rendering them. See raycastVehicle demo for an example.
  5436. * @method updateWheelTransform
  5437. * @param {integer} wheelIndex The wheel index to update.
  5438. */
  5439. RaycastVehicle.prototype.updateWheelTransform = function(wheelIndex){
  5440. var up = tmpVec4;
  5441. var right = tmpVec5;
  5442. var fwd = tmpVec6;
  5443. var wheel = this.wheelInfos[wheelIndex];
  5444. this.updateWheelTransformWorld(wheel);
  5445. wheel.directionLocal.scale(-1, up);
  5446. right.copy(wheel.axleLocal);
  5447. up.cross(right, fwd);
  5448. fwd.normalize();
  5449. right.normalize();
  5450. // Rotate around steering over the wheelAxle
  5451. var steering = wheel.steering;
  5452. var steeringOrn = new Quaternion();
  5453. steeringOrn.setFromAxisAngle(up, steering);
  5454. var rotatingOrn = new Quaternion();
  5455. rotatingOrn.setFromAxisAngle(right, wheel.rotation);
  5456. // World rotation of the wheel
  5457. var q = wheel.worldTransform.quaternion;
  5458. this.chassisBody.quaternion.mult(steeringOrn, q);
  5459. q.mult(rotatingOrn, q);
  5460. q.normalize();
  5461. // world position of the wheel
  5462. var p = wheel.worldTransform.position;
  5463. p.copy(wheel.directionWorld);
  5464. p.scale(wheel.suspensionLength, p);
  5465. p.vadd(wheel.chassisConnectionPointWorld, p);
  5466. };
  5467. var directions = [
  5468. new Vec3(1, 0, 0),
  5469. new Vec3(0, 1, 0),
  5470. new Vec3(0, 0, 1)
  5471. ];
  5472. /**
  5473. * Get the world transform of one of the wheels
  5474. * @method getWheelTransformWorld
  5475. * @param {integer} wheelIndex
  5476. * @return {Transform}
  5477. */
  5478. RaycastVehicle.prototype.getWheelTransformWorld = function(wheelIndex) {
  5479. return this.wheelInfos[wheelIndex].worldTransform;
  5480. };
  5481. var updateFriction_surfNormalWS_scaled_proj = new Vec3();
  5482. var updateFriction_axle = [];
  5483. var updateFriction_forwardWS = [];
  5484. var sideFrictionStiffness2 = 1;
  5485. RaycastVehicle.prototype.updateFriction = function(timeStep) {
  5486. var surfNormalWS_scaled_proj = updateFriction_surfNormalWS_scaled_proj;
  5487. //calculate the impulse, so that the wheels don't move sidewards
  5488. var wheelInfos = this.wheelInfos;
  5489. var numWheels = wheelInfos.length;
  5490. var chassisBody = this.chassisBody;
  5491. var forwardWS = updateFriction_forwardWS;
  5492. var axle = updateFriction_axle;
  5493. var numWheelsOnGround = 0;
  5494. for (var i = 0; i < numWheels; i++) {
  5495. var wheel = wheelInfos[i];
  5496. var groundObject = wheel.raycastResult.body;
  5497. if (groundObject){
  5498. numWheelsOnGround++;
  5499. }
  5500. wheel.sideImpulse = 0;
  5501. wheel.forwardImpulse = 0;
  5502. if(!forwardWS[i]){
  5503. forwardWS[i] = new Vec3();
  5504. }
  5505. if(!axle[i]){
  5506. axle[i] = new Vec3();
  5507. }
  5508. }
  5509. for (var i = 0; i < numWheels; i++){
  5510. var wheel = wheelInfos[i];
  5511. var groundObject = wheel.raycastResult.body;
  5512. if (groundObject) {
  5513. var axlei = axle[i];
  5514. var wheelTrans = this.getWheelTransformWorld(i);
  5515. // Get world axle
  5516. wheelTrans.vectorToWorldFrame(directions[this.indexRightAxis], axlei);
  5517. var surfNormalWS = wheel.raycastResult.hitNormalWorld;
  5518. var proj = axlei.dot(surfNormalWS);
  5519. surfNormalWS.scale(proj, surfNormalWS_scaled_proj);
  5520. axlei.vsub(surfNormalWS_scaled_proj, axlei);
  5521. axlei.normalize();
  5522. surfNormalWS.cross(axlei, forwardWS[i]);
  5523. forwardWS[i].normalize();
  5524. wheel.sideImpulse = resolveSingleBilateral(
  5525. chassisBody,
  5526. wheel.raycastResult.hitPointWorld,
  5527. groundObject,
  5528. wheel.raycastResult.hitPointWorld,
  5529. axlei
  5530. );
  5531. wheel.sideImpulse *= sideFrictionStiffness2;
  5532. }
  5533. }
  5534. var sideFactor = 1;
  5535. var fwdFactor = 0.5;
  5536. this.sliding = false;
  5537. for (var i = 0; i < numWheels; i++) {
  5538. var wheel = wheelInfos[i];
  5539. var groundObject = wheel.raycastResult.body;
  5540. var rollingFriction = 0;
  5541. wheel.slipInfo = 1;
  5542. if (groundObject) {
  5543. var defaultRollingFrictionImpulse = 0;
  5544. var maxImpulse = wheel.brake ? wheel.brake : defaultRollingFrictionImpulse;
  5545. // btWheelContactPoint contactPt(chassisBody,groundObject,wheelInfraycastInfo.hitPointWorld,forwardWS[wheel],maxImpulse);
  5546. // rollingFriction = calcRollingFriction(contactPt);
  5547. rollingFriction = calcRollingFriction(chassisBody, groundObject, wheel.raycastResult.hitPointWorld, forwardWS[i], maxImpulse);
  5548. rollingFriction += wheel.engineForce * timeStep;
  5549. // rollingFriction = 0;
  5550. var factor = maxImpulse / rollingFriction;
  5551. wheel.slipInfo *= factor;
  5552. }
  5553. //switch between active rolling (throttle), braking and non-active rolling friction (nthrottle/break)
  5554. wheel.forwardImpulse = 0;
  5555. wheel.skidInfo = 1;
  5556. if (groundObject) {
  5557. wheel.skidInfo = 1;
  5558. var maximp = wheel.suspensionForce * timeStep * wheel.frictionSlip;
  5559. var maximpSide = maximp;
  5560. var maximpSquared = maximp * maximpSide;
  5561. wheel.forwardImpulse = rollingFriction;//wheelInfo.engineForce* timeStep;
  5562. var x = wheel.forwardImpulse * fwdFactor;
  5563. var y = wheel.sideImpulse * sideFactor;
  5564. var impulseSquared = x * x + y * y;
  5565. wheel.sliding = false;
  5566. if (impulseSquared > maximpSquared) {
  5567. this.sliding = true;
  5568. wheel.sliding = true;
  5569. var factor = maximp / Math.sqrt(impulseSquared);
  5570. wheel.skidInfo *= factor;
  5571. }
  5572. }
  5573. }
  5574. if (this.sliding) {
  5575. for (var i = 0; i < numWheels; i++) {
  5576. var wheel = wheelInfos[i];
  5577. if (wheel.sideImpulse !== 0) {
  5578. if (wheel.skidInfo < 1){
  5579. wheel.forwardImpulse *= wheel.skidInfo;
  5580. wheel.sideImpulse *= wheel.skidInfo;
  5581. }
  5582. }
  5583. }
  5584. }
  5585. // apply the impulses
  5586. for (var i = 0; i < numWheels; i++) {
  5587. var wheel = wheelInfos[i];
  5588. var rel_pos = new Vec3();
  5589. //wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, rel_pos);
  5590. // cannons applyimpulse is using world coord for the position
  5591. rel_pos.copy(wheel.raycastResult.hitPointWorld);
  5592. if (wheel.forwardImpulse !== 0) {
  5593. var impulse = new Vec3();
  5594. forwardWS[i].scale(wheel.forwardImpulse, impulse);
  5595. chassisBody.applyImpulse(impulse, rel_pos);
  5596. }
  5597. if (wheel.sideImpulse !== 0){
  5598. var groundObject = wheel.raycastResult.body;
  5599. var rel_pos2 = new Vec3();
  5600. //wheel.raycastResult.hitPointWorld.vsub(groundObject.position, rel_pos2);
  5601. rel_pos2.copy(wheel.raycastResult.hitPointWorld);
  5602. var sideImp = new Vec3();
  5603. axle[i].scale(wheel.sideImpulse, sideImp);
  5604. // Scale the relative position in the up direction with rollInfluence.
  5605. // If rollInfluence is 1, the impulse will be applied on the hitPoint (easy to roll over), if it is zero it will be applied in the same plane as the center of mass (not easy to roll over).
  5606. chassisBody.pointToLocalFrame(rel_pos, rel_pos);
  5607. rel_pos['xyz'[this.indexUpAxis]] *= wheel.rollInfluence;
  5608. chassisBody.pointToWorldFrame(rel_pos, rel_pos);
  5609. chassisBody.applyImpulse(sideImp, rel_pos);
  5610. //apply friction impulse on the ground
  5611. sideImp.scale(-1, sideImp);
  5612. groundObject.applyImpulse(sideImp, rel_pos2);
  5613. }
  5614. }
  5615. };
  5616. var calcRollingFriction_vel1 = new Vec3();
  5617. var calcRollingFriction_vel2 = new Vec3();
  5618. var calcRollingFriction_vel = new Vec3();
  5619. function calcRollingFriction(body0, body1, frictionPosWorld, frictionDirectionWorld, maxImpulse) {
  5620. var j1 = 0;
  5621. var contactPosWorld = frictionPosWorld;
  5622. // var rel_pos1 = new Vec3();
  5623. // var rel_pos2 = new Vec3();
  5624. var vel1 = calcRollingFriction_vel1;
  5625. var vel2 = calcRollingFriction_vel2;
  5626. var vel = calcRollingFriction_vel;
  5627. // contactPosWorld.vsub(body0.position, rel_pos1);
  5628. // contactPosWorld.vsub(body1.position, rel_pos2);
  5629. body0.getVelocityAtWorldPoint(contactPosWorld, vel1);
  5630. body1.getVelocityAtWorldPoint(contactPosWorld, vel2);
  5631. vel1.vsub(vel2, vel);
  5632. var vrel = frictionDirectionWorld.dot(vel);
  5633. var denom0 = computeImpulseDenominator(body0, frictionPosWorld, frictionDirectionWorld);
  5634. var denom1 = computeImpulseDenominator(body1, frictionPosWorld, frictionDirectionWorld);
  5635. var relaxation = 1;
  5636. var jacDiagABInv = relaxation / (denom0 + denom1);
  5637. // calculate j that moves us to zero relative velocity
  5638. j1 = -vrel * jacDiagABInv;
  5639. if (maxImpulse < j1) {
  5640. j1 = maxImpulse;
  5641. }
  5642. if (j1 < -maxImpulse) {
  5643. j1 = -maxImpulse;
  5644. }
  5645. return j1;
  5646. }
  5647. var computeImpulseDenominator_r0 = new Vec3();
  5648. var computeImpulseDenominator_c0 = new Vec3();
  5649. var computeImpulseDenominator_vec = new Vec3();
  5650. var computeImpulseDenominator_m = new Vec3();
  5651. function computeImpulseDenominator(body, pos, normal) {
  5652. var r0 = computeImpulseDenominator_r0;
  5653. var c0 = computeImpulseDenominator_c0;
  5654. var vec = computeImpulseDenominator_vec;
  5655. var m = computeImpulseDenominator_m;
  5656. pos.vsub(body.position, r0);
  5657. r0.cross(normal, c0);
  5658. body.invInertiaWorld.vmult(c0, m);
  5659. m.cross(r0, vec);
  5660. return body.invMass + normal.dot(vec);
  5661. }
  5662. var resolveSingleBilateral_vel1 = new Vec3();
  5663. var resolveSingleBilateral_vel2 = new Vec3();
  5664. var resolveSingleBilateral_vel = new Vec3();
  5665. //bilateral constraint between two dynamic objects
  5666. function resolveSingleBilateral(body1, pos1, body2, pos2, normal, impulse){
  5667. var normalLenSqr = normal.norm2();
  5668. if (normalLenSqr > 1.1){
  5669. return 0; // no impulse
  5670. }
  5671. // var rel_pos1 = new Vec3();
  5672. // var rel_pos2 = new Vec3();
  5673. // pos1.vsub(body1.position, rel_pos1);
  5674. // pos2.vsub(body2.position, rel_pos2);
  5675. var vel1 = resolveSingleBilateral_vel1;
  5676. var vel2 = resolveSingleBilateral_vel2;
  5677. var vel = resolveSingleBilateral_vel;
  5678. body1.getVelocityAtWorldPoint(pos1, vel1);
  5679. body2.getVelocityAtWorldPoint(pos2, vel2);
  5680. vel1.vsub(vel2, vel);
  5681. var rel_vel = normal.dot(vel);
  5682. var contactDamping = 0.2;
  5683. var massTerm = 1 / (body1.invMass + body2.invMass);
  5684. var impulse = - contactDamping * rel_vel * massTerm;
  5685. return impulse;
  5686. }
  5687. },{"../collision/Ray":9,"../collision/RaycastResult":10,"../math/Quaternion":28,"../math/Vec3":30,"../objects/WheelInfo":36,"./Body":31}],33:[function(_dereq_,module,exports){
  5688. var Body = _dereq_('./Body');
  5689. var Sphere = _dereq_('../shapes/Sphere');
  5690. var Box = _dereq_('../shapes/Box');
  5691. var Vec3 = _dereq_('../math/Vec3');
  5692. var HingeConstraint = _dereq_('../constraints/HingeConstraint');
  5693. module.exports = RigidVehicle;
  5694. /**
  5695. * Simple vehicle helper class with spherical rigid body wheels.
  5696. * @class RigidVehicle
  5697. * @constructor
  5698. * @param {Body} [options.chassisBody]
  5699. */
  5700. function RigidVehicle(options){
  5701. this.wheelBodies = [];
  5702. /**
  5703. * @property coordinateSystem
  5704. * @type {Vec3}
  5705. */
  5706. this.coordinateSystem = typeof(options.coordinateSystem)==='undefined' ? new Vec3(1, 2, 3) : options.coordinateSystem.clone();
  5707. /**
  5708. * @property {Body} chassisBody
  5709. */
  5710. this.chassisBody = options.chassisBody;
  5711. if(!this.chassisBody){
  5712. // No chassis body given. Create it!
  5713. var chassisShape = new Box(new Vec3(5, 2, 0.5));
  5714. this.chassisBody = new Body(1, chassisShape);
  5715. }
  5716. /**
  5717. * @property constraints
  5718. * @type {Array}
  5719. */
  5720. this.constraints = [];
  5721. this.wheelAxes = [];
  5722. this.wheelForces = [];
  5723. }
  5724. /**
  5725. * Add a wheel
  5726. * @method addWheel
  5727. * @param {object} options
  5728. * @param {boolean} [options.isFrontWheel]
  5729. * @param {Vec3} [options.position] Position of the wheel, locally in the chassis body.
  5730. * @param {Vec3} [options.direction] Slide direction of the wheel along the suspension.
  5731. * @param {Vec3} [options.axis] Axis of rotation of the wheel, locally defined in the chassis.
  5732. * @param {Body} [options.body] The wheel body.
  5733. */
  5734. RigidVehicle.prototype.addWheel = function(options){
  5735. options = options || {};
  5736. var wheelBody = options.body;
  5737. if(!wheelBody){
  5738. wheelBody = new Body(1, new Sphere(1.2));
  5739. }
  5740. this.wheelBodies.push(wheelBody);
  5741. this.wheelForces.push(0);
  5742. // Position constrain wheels
  5743. var zero = new Vec3();
  5744. var position = typeof(options.position) !== 'undefined' ? options.position.clone() : new Vec3();
  5745. // Set position locally to the chassis
  5746. var worldPosition = new Vec3();
  5747. this.chassisBody.pointToWorldFrame(position, worldPosition);
  5748. wheelBody.position.set(worldPosition.x, worldPosition.y, worldPosition.z);
  5749. // Constrain wheel
  5750. var axis = typeof(options.axis) !== 'undefined' ? options.axis.clone() : new Vec3(0, 1, 0);
  5751. this.wheelAxes.push(axis);
  5752. var hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, {
  5753. pivotA: position,
  5754. axisA: axis,
  5755. pivotB: Vec3.ZERO,
  5756. axisB: axis,
  5757. collideConnected: false
  5758. });
  5759. this.constraints.push(hingeConstraint);
  5760. return this.wheelBodies.length - 1;
  5761. };
  5762. /**
  5763. * Set the steering value of a wheel.
  5764. * @method setSteeringValue
  5765. * @param {number} value
  5766. * @param {integer} wheelIndex
  5767. * @todo check coordinateSystem
  5768. */
  5769. RigidVehicle.prototype.setSteeringValue = function(value, wheelIndex){
  5770. // Set angle of the hinge axis
  5771. var axis = this.wheelAxes[wheelIndex];
  5772. var c = Math.cos(value),
  5773. s = Math.sin(value),
  5774. x = axis.x,
  5775. y = axis.y;
  5776. this.constraints[wheelIndex].axisA.set(
  5777. c*x -s*y,
  5778. s*x +c*y,
  5779. 0
  5780. );
  5781. };
  5782. /**
  5783. * Set the target rotational speed of the hinge constraint.
  5784. * @method setMotorSpeed
  5785. * @param {number} value
  5786. * @param {integer} wheelIndex
  5787. */
  5788. RigidVehicle.prototype.setMotorSpeed = function(value, wheelIndex){
  5789. var hingeConstraint = this.constraints[wheelIndex];
  5790. hingeConstraint.enableMotor();
  5791. hingeConstraint.motorTargetVelocity = value;
  5792. };
  5793. /**
  5794. * Set the target rotational speed of the hinge constraint.
  5795. * @method disableMotor
  5796. * @param {number} value
  5797. * @param {integer} wheelIndex
  5798. */
  5799. RigidVehicle.prototype.disableMotor = function(wheelIndex){
  5800. var hingeConstraint = this.constraints[wheelIndex];
  5801. hingeConstraint.disableMotor();
  5802. };
  5803. var torque = new Vec3();
  5804. /**
  5805. * Set the wheel force to apply on one of the wheels each time step
  5806. * @method setWheelForce
  5807. * @param {number} value
  5808. * @param {integer} wheelIndex
  5809. */
  5810. RigidVehicle.prototype.setWheelForce = function(value, wheelIndex){
  5811. this.wheelForces[wheelIndex] = value;
  5812. };
  5813. /**
  5814. * Apply a torque on one of the wheels.
  5815. * @method applyWheelForce
  5816. * @param {number} value
  5817. * @param {integer} wheelIndex
  5818. */
  5819. RigidVehicle.prototype.applyWheelForce = function(value, wheelIndex){
  5820. var axis = this.wheelAxes[wheelIndex];
  5821. var wheelBody = this.wheelBodies[wheelIndex];
  5822. var bodyTorque = wheelBody.torque;
  5823. axis.scale(value, torque);
  5824. wheelBody.vectorToWorldFrame(torque, torque);
  5825. bodyTorque.vadd(torque, bodyTorque);
  5826. };
  5827. /**
  5828. * Add the vehicle including its constraints to the world.
  5829. * @method addToWorld
  5830. * @param {World} world
  5831. */
  5832. RigidVehicle.prototype.addToWorld = function(world){
  5833. var constraints = this.constraints;
  5834. var bodies = this.wheelBodies.concat([this.chassisBody]);
  5835. for (var i = 0; i < bodies.length; i++) {
  5836. world.add(bodies[i]);
  5837. }
  5838. for (var i = 0; i < constraints.length; i++) {
  5839. world.addConstraint(constraints[i]);
  5840. }
  5841. world.addEventListener('preStep', this._update.bind(this));
  5842. };
  5843. RigidVehicle.prototype._update = function(){
  5844. var wheelForces = this.wheelForces;
  5845. for (var i = 0; i < wheelForces.length; i++) {
  5846. this.applyWheelForce(wheelForces[i], i);
  5847. }
  5848. };
  5849. /**
  5850. * Remove the vehicle including its constraints from the world.
  5851. * @method removeFromWorld
  5852. * @param {World} world
  5853. */
  5854. RigidVehicle.prototype.removeFromWorld = function(world){
  5855. var constraints = this.constraints;
  5856. var bodies = this.wheelBodies.concat([this.chassisBody]);
  5857. for (var i = 0; i < bodies.length; i++) {
  5858. world.remove(bodies[i]);
  5859. }
  5860. for (var i = 0; i < constraints.length; i++) {
  5861. world.removeConstraint(constraints[i]);
  5862. }
  5863. };
  5864. var worldAxis = new Vec3();
  5865. /**
  5866. * Get current rotational velocity of a wheel
  5867. * @method getWheelSpeed
  5868. * @param {integer} wheelIndex
  5869. */
  5870. RigidVehicle.prototype.getWheelSpeed = function(wheelIndex){
  5871. var axis = this.wheelAxes[wheelIndex];
  5872. var wheelBody = this.wheelBodies[wheelIndex];
  5873. var w = wheelBody.angularVelocity;
  5874. this.chassisBody.vectorToWorldFrame(axis, worldAxis);
  5875. return w.dot(worldAxis);
  5876. };
  5877. },{"../constraints/HingeConstraint":15,"../math/Vec3":30,"../shapes/Box":37,"../shapes/Sphere":44,"./Body":31}],34:[function(_dereq_,module,exports){
  5878. module.exports = SPHSystem;
  5879. var Shape = _dereq_('../shapes/Shape');
  5880. var Vec3 = _dereq_('../math/Vec3');
  5881. var Quaternion = _dereq_('../math/Quaternion');
  5882. var Particle = _dereq_('../shapes/Particle');
  5883. var Body = _dereq_('../objects/Body');
  5884. var Material = _dereq_('../material/Material');
  5885. /**
  5886. * Smoothed-particle hydrodynamics system
  5887. * @class SPHSystem
  5888. * @constructor
  5889. */
  5890. function SPHSystem(){
  5891. this.particles = [];
  5892. /**
  5893. * Density of the system (kg/m3).
  5894. * @property {number} density
  5895. */
  5896. this.density = 1;
  5897. /**
  5898. * Distance below which two particles are considered to be neighbors.
  5899. * It should be adjusted so there are about 15-20 neighbor particles within this radius.
  5900. * @property {number} smoothingRadius
  5901. */
  5902. this.smoothingRadius = 1;
  5903. this.speedOfSound = 1;
  5904. /**
  5905. * Viscosity of the system.
  5906. * @property {number} viscosity
  5907. */
  5908. this.viscosity = 0.01;
  5909. this.eps = 0.000001;
  5910. // Stuff Computed per particle
  5911. this.pressures = [];
  5912. this.densities = [];
  5913. this.neighbors = [];
  5914. }
  5915. /**
  5916. * Add a particle to the system.
  5917. * @method add
  5918. * @param {Body} particle
  5919. */
  5920. SPHSystem.prototype.add = function(particle){
  5921. this.particles.push(particle);
  5922. if(this.neighbors.length < this.particles.length){
  5923. this.neighbors.push([]);
  5924. }
  5925. };
  5926. /**
  5927. * Remove a particle from the system.
  5928. * @method remove
  5929. * @param {Body} particle
  5930. */
  5931. SPHSystem.prototype.remove = function(particle){
  5932. var idx = this.particles.indexOf(particle);
  5933. if(idx !== -1){
  5934. this.particles.splice(idx,1);
  5935. if(this.neighbors.length > this.particles.length){
  5936. this.neighbors.pop();
  5937. }
  5938. }
  5939. };
  5940. /**
  5941. * Get neighbors within smoothing volume, save in the array neighbors
  5942. * @method getNeighbors
  5943. * @param {Body} particle
  5944. * @param {Array} neighbors
  5945. */
  5946. var SPHSystem_getNeighbors_dist = new Vec3();
  5947. SPHSystem.prototype.getNeighbors = function(particle,neighbors){
  5948. var N = this.particles.length,
  5949. id = particle.id,
  5950. R2 = this.smoothingRadius * this.smoothingRadius,
  5951. dist = SPHSystem_getNeighbors_dist;
  5952. for(var i=0; i!==N; i++){
  5953. var p = this.particles[i];
  5954. p.position.vsub(particle.position,dist);
  5955. if(id!==p.id && dist.norm2() < R2){
  5956. neighbors.push(p);
  5957. }
  5958. }
  5959. };
  5960. // Temp vectors for calculation
  5961. var SPHSystem_update_dist = new Vec3(),
  5962. SPHSystem_update_a_pressure = new Vec3(),
  5963. SPHSystem_update_a_visc = new Vec3(),
  5964. SPHSystem_update_gradW = new Vec3(),
  5965. SPHSystem_update_r_vec = new Vec3(),
  5966. SPHSystem_update_u = new Vec3(); // Relative velocity
  5967. SPHSystem.prototype.update = function(){
  5968. var N = this.particles.length,
  5969. dist = SPHSystem_update_dist,
  5970. cs = this.speedOfSound,
  5971. eps = this.eps;
  5972. for(var i=0; i!==N; i++){
  5973. var p = this.particles[i]; // Current particle
  5974. var neighbors = this.neighbors[i];
  5975. // Get neighbors
  5976. neighbors.length = 0;
  5977. this.getNeighbors(p,neighbors);
  5978. neighbors.push(this.particles[i]); // Add current too
  5979. var numNeighbors = neighbors.length;
  5980. // Accumulate density for the particle
  5981. var sum = 0.0;
  5982. for(var j=0; j!==numNeighbors; j++){
  5983. //printf("Current particle has position %f %f %f\n",objects[id].pos.x(),objects[id].pos.y(),objects[id].pos.z());
  5984. p.position.vsub(neighbors[j].position, dist);
  5985. var len = dist.norm();
  5986. var weight = this.w(len);
  5987. sum += neighbors[j].mass * weight;
  5988. }
  5989. // Save
  5990. this.densities[i] = sum;
  5991. this.pressures[i] = cs * cs * (this.densities[i] - this.density);
  5992. }
  5993. // Add forces
  5994. // Sum to these accelerations
  5995. var a_pressure= SPHSystem_update_a_pressure;
  5996. var a_visc = SPHSystem_update_a_visc;
  5997. var gradW = SPHSystem_update_gradW;
  5998. var r_vec = SPHSystem_update_r_vec;
  5999. var u = SPHSystem_update_u;
  6000. for(var i=0; i!==N; i++){
  6001. var particle = this.particles[i];
  6002. a_pressure.set(0,0,0);
  6003. a_visc.set(0,0,0);
  6004. // Init vars
  6005. var Pij;
  6006. var nabla;
  6007. var Vij;
  6008. // Sum up for all other neighbors
  6009. var neighbors = this.neighbors[i];
  6010. var numNeighbors = neighbors.length;
  6011. //printf("Neighbors: ");
  6012. for(var j=0; j!==numNeighbors; j++){
  6013. var neighbor = neighbors[j];
  6014. //printf("%d ",nj);
  6015. // Get r once for all..
  6016. particle.position.vsub(neighbor.position,r_vec);
  6017. var r = r_vec.norm();
  6018. // Pressure contribution
  6019. Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i]*this.densities[i] + eps) + this.pressures[j] / (this.densities[j]*this.densities[j] + eps));
  6020. this.gradw(r_vec, gradW);
  6021. // Add to pressure acceleration
  6022. gradW.mult(Pij , gradW);
  6023. a_pressure.vadd(gradW, a_pressure);
  6024. // Viscosity contribution
  6025. neighbor.velocity.vsub(particle.velocity, u);
  6026. u.mult( 1.0 / (0.0001+this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass , u );
  6027. nabla = this.nablaw(r);
  6028. u.mult(nabla,u);
  6029. // Add to viscosity acceleration
  6030. a_visc.vadd( u, a_visc );
  6031. }
  6032. // Calculate force
  6033. a_visc.mult(particle.mass, a_visc);
  6034. a_pressure.mult(particle.mass, a_pressure);
  6035. // Add force to particles
  6036. particle.force.vadd(a_visc, particle.force);
  6037. particle.force.vadd(a_pressure, particle.force);
  6038. }
  6039. };
  6040. // Calculate the weight using the W(r) weightfunction
  6041. SPHSystem.prototype.w = function(r){
  6042. // 315
  6043. var h = this.smoothingRadius;
  6044. return 315.0/(64.0*Math.PI*Math.pow(h,9)) * Math.pow(h*h-r*r,3);
  6045. };
  6046. // calculate gradient of the weight function
  6047. SPHSystem.prototype.gradw = function(rVec,resultVec){
  6048. var r = rVec.norm(),
  6049. h = this.smoothingRadius;
  6050. rVec.mult(945.0/(32.0*Math.PI*Math.pow(h,9)) * Math.pow((h*h-r*r),2) , resultVec);
  6051. };
  6052. // Calculate nabla(W)
  6053. SPHSystem.prototype.nablaw = function(r){
  6054. var h = this.smoothingRadius;
  6055. var nabla = 945.0/(32.0*Math.PI*Math.pow(h,9)) * (h*h-r*r)*(7*r*r - 3*h*h);
  6056. return nabla;
  6057. };
  6058. },{"../material/Material":25,"../math/Quaternion":28,"../math/Vec3":30,"../objects/Body":31,"../shapes/Particle":41,"../shapes/Shape":43}],35:[function(_dereq_,module,exports){
  6059. var Vec3 = _dereq_('../math/Vec3');
  6060. module.exports = Spring;
  6061. /**
  6062. * A spring, connecting two bodies.
  6063. *
  6064. * @class Spring
  6065. * @constructor
  6066. * @param {Body} bodyA
  6067. * @param {Body} bodyB
  6068. * @param {Object} [options]
  6069. * @param {number} [options.restLength] A number > 0. Default: 1
  6070. * @param {number} [options.stiffness] A number >= 0. Default: 100
  6071. * @param {number} [options.damping] A number >= 0. Default: 1
  6072. * @param {Vec3} [options.worldAnchorA] Where to hook the spring to body A, in world coordinates.
  6073. * @param {Vec3} [options.worldAnchorB]
  6074. * @param {Vec3} [options.localAnchorA] Where to hook the spring to body A, in local body coordinates.
  6075. * @param {Vec3} [options.localAnchorB]
  6076. */
  6077. function Spring(bodyA,bodyB,options){
  6078. options = options || {};
  6079. /**
  6080. * Rest length of the spring.
  6081. * @property restLength
  6082. * @type {number}
  6083. */
  6084. this.restLength = typeof(options.restLength) === "number" ? options.restLength : 1;
  6085. /**
  6086. * Stiffness of the spring.
  6087. * @property stiffness
  6088. * @type {number}
  6089. */
  6090. this.stiffness = options.stiffness || 100;
  6091. /**
  6092. * Damping of the spring.
  6093. * @property damping
  6094. * @type {number}
  6095. */
  6096. this.damping = options.damping || 1;
  6097. /**
  6098. * First connected body.
  6099. * @property bodyA
  6100. * @type {Body}
  6101. */
  6102. this.bodyA = bodyA;
  6103. /**
  6104. * Second connected body.
  6105. * @property bodyB
  6106. * @type {Body}
  6107. */
  6108. this.bodyB = bodyB;
  6109. /**
  6110. * Anchor for bodyA in local bodyA coordinates.
  6111. * @property localAnchorA
  6112. * @type {Vec3}
  6113. */
  6114. this.localAnchorA = new Vec3();
  6115. /**
  6116. * Anchor for bodyB in local bodyB coordinates.
  6117. * @property localAnchorB
  6118. * @type {Vec3}
  6119. */
  6120. this.localAnchorB = new Vec3();
  6121. if(options.localAnchorA){
  6122. this.localAnchorA.copy(options.localAnchorA);
  6123. }
  6124. if(options.localAnchorB){
  6125. this.localAnchorB.copy(options.localAnchorB);
  6126. }
  6127. if(options.worldAnchorA){
  6128. this.setWorldAnchorA(options.worldAnchorA);
  6129. }
  6130. if(options.worldAnchorB){
  6131. this.setWorldAnchorB(options.worldAnchorB);
  6132. }
  6133. }
  6134. /**
  6135. * Set the anchor point on body A, using world coordinates.
  6136. * @method setWorldAnchorA
  6137. * @param {Vec3} worldAnchorA
  6138. */
  6139. Spring.prototype.setWorldAnchorA = function(worldAnchorA){
  6140. this.bodyA.pointToLocalFrame(worldAnchorA,this.localAnchorA);
  6141. };
  6142. /**
  6143. * Set the anchor point on body B, using world coordinates.
  6144. * @method setWorldAnchorB
  6145. * @param {Vec3} worldAnchorB
  6146. */
  6147. Spring.prototype.setWorldAnchorB = function(worldAnchorB){
  6148. this.bodyB.pointToLocalFrame(worldAnchorB,this.localAnchorB);
  6149. };
  6150. /**
  6151. * Get the anchor point on body A, in world coordinates.
  6152. * @method getWorldAnchorA
  6153. * @param {Vec3} result The vector to store the result in.
  6154. */
  6155. Spring.prototype.getWorldAnchorA = function(result){
  6156. this.bodyA.pointToWorldFrame(this.localAnchorA,result);
  6157. };
  6158. /**
  6159. * Get the anchor point on body B, in world coordinates.
  6160. * @method getWorldAnchorB
  6161. * @param {Vec3} result The vector to store the result in.
  6162. */
  6163. Spring.prototype.getWorldAnchorB = function(result){
  6164. this.bodyB.pointToWorldFrame(this.localAnchorB,result);
  6165. };
  6166. var applyForce_r = new Vec3(),
  6167. applyForce_r_unit = new Vec3(),
  6168. applyForce_u = new Vec3(),
  6169. applyForce_f = new Vec3(),
  6170. applyForce_worldAnchorA = new Vec3(),
  6171. applyForce_worldAnchorB = new Vec3(),
  6172. applyForce_ri = new Vec3(),
  6173. applyForce_rj = new Vec3(),
  6174. applyForce_ri_x_f = new Vec3(),
  6175. applyForce_rj_x_f = new Vec3(),
  6176. applyForce_tmp = new Vec3();
  6177. /**
  6178. * Apply the spring force to the connected bodies.
  6179. * @method applyForce
  6180. */
  6181. Spring.prototype.applyForce = function(){
  6182. var k = this.stiffness,
  6183. d = this.damping,
  6184. l = this.restLength,
  6185. bodyA = this.bodyA,
  6186. bodyB = this.bodyB,
  6187. r = applyForce_r,
  6188. r_unit = applyForce_r_unit,
  6189. u = applyForce_u,
  6190. f = applyForce_f,
  6191. tmp = applyForce_tmp;
  6192. var worldAnchorA = applyForce_worldAnchorA,
  6193. worldAnchorB = applyForce_worldAnchorB,
  6194. ri = applyForce_ri,
  6195. rj = applyForce_rj,
  6196. ri_x_f = applyForce_ri_x_f,
  6197. rj_x_f = applyForce_rj_x_f;
  6198. // Get world anchors
  6199. this.getWorldAnchorA(worldAnchorA);
  6200. this.getWorldAnchorB(worldAnchorB);
  6201. // Get offset points
  6202. worldAnchorA.vsub(bodyA.position,ri);
  6203. worldAnchorB.vsub(bodyB.position,rj);
  6204. // Compute distance vector between world anchor points
  6205. worldAnchorB.vsub(worldAnchorA,r);
  6206. var rlen = r.norm();
  6207. r_unit.copy(r);
  6208. r_unit.normalize();
  6209. // Compute relative velocity of the anchor points, u
  6210. bodyB.velocity.vsub(bodyA.velocity,u);
  6211. // Add rotational velocity
  6212. bodyB.angularVelocity.cross(rj,tmp);
  6213. u.vadd(tmp,u);
  6214. bodyA.angularVelocity.cross(ri,tmp);
  6215. u.vsub(tmp,u);
  6216. // F = - k * ( x - L ) - D * ( u )
  6217. r_unit.mult(-k*(rlen-l) - d*u.dot(r_unit), f);
  6218. // Add forces to bodies
  6219. bodyA.force.vsub(f,bodyA.force);
  6220. bodyB.force.vadd(f,bodyB.force);
  6221. // Angular force
  6222. ri.cross(f,ri_x_f);
  6223. rj.cross(f,rj_x_f);
  6224. bodyA.torque.vsub(ri_x_f,bodyA.torque);
  6225. bodyB.torque.vadd(rj_x_f,bodyB.torque);
  6226. };
  6227. },{"../math/Vec3":30}],36:[function(_dereq_,module,exports){
  6228. var Vec3 = _dereq_('../math/Vec3');
  6229. var Transform = _dereq_('../math/Transform');
  6230. var RaycastResult = _dereq_('../collision/RaycastResult');
  6231. var Utils = _dereq_('../utils/Utils');
  6232. module.exports = WheelInfo;
  6233. /**
  6234. * @class WheelInfo
  6235. * @constructor
  6236. * @param {Object} [options]
  6237. *
  6238. * @param {Vec3} [options.chassisConnectionPointLocal]
  6239. * @param {Vec3} [options.chassisConnectionPointWorld]
  6240. * @param {Vec3} [options.directionLocal]
  6241. * @param {Vec3} [options.directionWorld]
  6242. * @param {Vec3} [options.axleLocal]
  6243. * @param {Vec3} [options.axleWorld]
  6244. * @param {number} [options.suspensionRestLength=1]
  6245. * @param {number} [options.suspensionMaxLength=2]
  6246. * @param {number} [options.radius=1]
  6247. * @param {number} [options.suspensionStiffness=100]
  6248. * @param {number} [options.dampingCompression=10]
  6249. * @param {number} [options.dampingRelaxation=10]
  6250. * @param {number} [options.frictionSlip=10000]
  6251. * @param {number} [options.steering=0]
  6252. * @param {number} [options.rotation=0]
  6253. * @param {number} [options.deltaRotation=0]
  6254. * @param {number} [options.rollInfluence=0.01]
  6255. * @param {number} [options.maxSuspensionForce]
  6256. * @param {boolean} [options.isFrontWheel=true]
  6257. * @param {number} [options.clippedInvContactDotSuspension=1]
  6258. * @param {number} [options.suspensionRelativeVelocity=0]
  6259. * @param {number} [options.suspensionForce=0]
  6260. * @param {number} [options.skidInfo=0]
  6261. * @param {number} [options.suspensionLength=0]
  6262. * @param {number} [options.maxSuspensionTravel=1]
  6263. * @param {boolean} [options.useCustomSlidingRotationalSpeed=false]
  6264. * @param {number} [options.customSlidingRotationalSpeed=-0.1]
  6265. */
  6266. function WheelInfo(options){
  6267. options = Utils.defaults(options, {
  6268. chassisConnectionPointLocal: new Vec3(),
  6269. chassisConnectionPointWorld: new Vec3(),
  6270. directionLocal: new Vec3(),
  6271. directionWorld: new Vec3(),
  6272. axleLocal: new Vec3(),
  6273. axleWorld: new Vec3(),
  6274. suspensionRestLength: 1,
  6275. suspensionMaxLength: 2,
  6276. radius: 1,
  6277. suspensionStiffness: 100,
  6278. dampingCompression: 10,
  6279. dampingRelaxation: 10,
  6280. frictionSlip: 10000,
  6281. steering: 0,
  6282. rotation: 0,
  6283. deltaRotation: 0,
  6284. rollInfluence: 0.01,
  6285. maxSuspensionForce: Number.MAX_VALUE,
  6286. isFrontWheel: true,
  6287. clippedInvContactDotSuspension: 1,
  6288. suspensionRelativeVelocity: 0,
  6289. suspensionForce: 0,
  6290. skidInfo: 0,
  6291. suspensionLength: 0,
  6292. maxSuspensionTravel: 1,
  6293. useCustomSlidingRotationalSpeed: false,
  6294. customSlidingRotationalSpeed: -0.1
  6295. });
  6296. /**
  6297. * Max travel distance of the suspension, in meters.
  6298. * @property {number} maxSuspensionTravel
  6299. */
  6300. this.maxSuspensionTravel = options.maxSuspensionTravel;
  6301. /**
  6302. * Speed to apply to the wheel rotation when the wheel is sliding.
  6303. * @property {number} customSlidingRotationalSpeed
  6304. */
  6305. this.customSlidingRotationalSpeed = options.customSlidingRotationalSpeed;
  6306. /**
  6307. * If the customSlidingRotationalSpeed should be used.
  6308. * @property {Boolean} useCustomSlidingRotationalSpeed
  6309. */
  6310. this.useCustomSlidingRotationalSpeed = options.useCustomSlidingRotationalSpeed;
  6311. /**
  6312. * @property {Boolean} sliding
  6313. */
  6314. this.sliding = false;
  6315. /**
  6316. * Connection point, defined locally in the chassis body frame.
  6317. * @property {Vec3} chassisConnectionPointLocal
  6318. */
  6319. this.chassisConnectionPointLocal = options.chassisConnectionPointLocal.clone();
  6320. /**
  6321. * @property {Vec3} chassisConnectionPointWorld
  6322. */
  6323. this.chassisConnectionPointWorld = options.chassisConnectionPointWorld.clone();
  6324. /**
  6325. * @property {Vec3} directionLocal
  6326. */
  6327. this.directionLocal = options.directionLocal.clone();
  6328. /**
  6329. * @property {Vec3} directionWorld
  6330. */
  6331. this.directionWorld = options.directionWorld.clone();
  6332. /**
  6333. * @property {Vec3} axleLocal
  6334. */
  6335. this.axleLocal = options.axleLocal.clone();
  6336. /**
  6337. * @property {Vec3} axleWorld
  6338. */
  6339. this.axleWorld = options.axleWorld.clone();
  6340. /**
  6341. * @property {number} suspensionRestLength
  6342. */
  6343. this.suspensionRestLength = options.suspensionRestLength;
  6344. /**
  6345. * @property {number} suspensionMaxLength
  6346. */
  6347. this.suspensionMaxLength = options.suspensionMaxLength;
  6348. /**
  6349. * @property {number} radius
  6350. */
  6351. this.radius = options.radius;
  6352. /**
  6353. * @property {number} suspensionStiffness
  6354. */
  6355. this.suspensionStiffness = options.suspensionStiffness;
  6356. /**
  6357. * @property {number} dampingCompression
  6358. */
  6359. this.dampingCompression = options.dampingCompression;
  6360. /**
  6361. * @property {number} dampingRelaxation
  6362. */
  6363. this.dampingRelaxation = options.dampingRelaxation;
  6364. /**
  6365. * @property {number} frictionSlip
  6366. */
  6367. this.frictionSlip = options.frictionSlip;
  6368. /**
  6369. * @property {number} steering
  6370. */
  6371. this.steering = 0;
  6372. /**
  6373. * Rotation value, in radians.
  6374. * @property {number} rotation
  6375. */
  6376. this.rotation = 0;
  6377. /**
  6378. * @property {number} deltaRotation
  6379. */
  6380. this.deltaRotation = 0;
  6381. /**
  6382. * @property {number} rollInfluence
  6383. */
  6384. this.rollInfluence = options.rollInfluence;
  6385. /**
  6386. * @property {number} maxSuspensionForce
  6387. */
  6388. this.maxSuspensionForce = options.maxSuspensionForce;
  6389. /**
  6390. * @property {number} engineForce
  6391. */
  6392. this.engineForce = 0;
  6393. /**
  6394. * @property {number} brake
  6395. */
  6396. this.brake = 0;
  6397. /**
  6398. * @property {number} isFrontWheel
  6399. */
  6400. this.isFrontWheel = options.isFrontWheel;
  6401. /**
  6402. * @property {number} clippedInvContactDotSuspension
  6403. */
  6404. this.clippedInvContactDotSuspension = 1;
  6405. /**
  6406. * @property {number} suspensionRelativeVelocity
  6407. */
  6408. this.suspensionRelativeVelocity = 0;
  6409. /**
  6410. * @property {number} suspensionForce
  6411. */
  6412. this.suspensionForce = 0;
  6413. /**
  6414. * @property {number} skidInfo
  6415. */
  6416. this.skidInfo = 0;
  6417. /**
  6418. * @property {number} suspensionLength
  6419. */
  6420. this.suspensionLength = 0;
  6421. /**
  6422. * @property {number} sideImpulse
  6423. */
  6424. this.sideImpulse = 0;
  6425. /**
  6426. * @property {number} forwardImpulse
  6427. */
  6428. this.forwardImpulse = 0;
  6429. /**
  6430. * The result from raycasting
  6431. * @property {RaycastResult} raycastResult
  6432. */
  6433. this.raycastResult = new RaycastResult();
  6434. /**
  6435. * Wheel world transform
  6436. * @property {Transform} worldTransform
  6437. */
  6438. this.worldTransform = new Transform();
  6439. /**
  6440. * @property {boolean} isInContact
  6441. */
  6442. this.isInContact = false;
  6443. }
  6444. var chassis_velocity_at_contactPoint = new Vec3();
  6445. var relpos = new Vec3();
  6446. var chassis_velocity_at_contactPoint = new Vec3();
  6447. WheelInfo.prototype.updateWheel = function(chassis){
  6448. var raycastResult = this.raycastResult;
  6449. if (this.isInContact){
  6450. var project= raycastResult.hitNormalWorld.dot(raycastResult.directionWorld);
  6451. raycastResult.hitPointWorld.vsub(chassis.position, relpos);
  6452. chassis.getVelocityAtWorldPoint(relpos, chassis_velocity_at_contactPoint);
  6453. var projVel = raycastResult.hitNormalWorld.dot( chassis_velocity_at_contactPoint );
  6454. if (project >= -0.1) {
  6455. this.suspensionRelativeVelocity = 0.0;
  6456. this.clippedInvContactDotSuspension = 1.0 / 0.1;
  6457. } else {
  6458. var inv = -1 / project;
  6459. this.suspensionRelativeVelocity = projVel * inv;
  6460. this.clippedInvContactDotSuspension = inv;
  6461. }
  6462. } else {
  6463. // Not in contact : position wheel in a nice (rest length) position
  6464. raycastResult.suspensionLength = this.suspensionRestLength;
  6465. this.suspensionRelativeVelocity = 0.0;
  6466. raycastResult.directionWorld.scale(-1, raycastResult.hitNormalWorld);
  6467. this.clippedInvContactDotSuspension = 1.0;
  6468. }
  6469. };
  6470. },{"../collision/RaycastResult":10,"../math/Transform":29,"../math/Vec3":30,"../utils/Utils":53}],37:[function(_dereq_,module,exports){
  6471. module.exports = Box;
  6472. var Shape = _dereq_('./Shape');
  6473. var Vec3 = _dereq_('../math/Vec3');
  6474. var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
  6475. /**
  6476. * A 3d box shape.
  6477. * @class Box
  6478. * @constructor
  6479. * @param {Vec3} halfExtents
  6480. * @author schteppe
  6481. * @extends Shape
  6482. */
  6483. function Box(halfExtents){
  6484. Shape.call(this);
  6485. this.type = Shape.types.BOX;
  6486. /**
  6487. * @property halfExtents
  6488. * @type {Vec3}
  6489. */
  6490. this.halfExtents = halfExtents;
  6491. /**
  6492. * Used by the contact generator to make contacts with other convex polyhedra for example
  6493. * @property convexPolyhedronRepresentation
  6494. * @type {ConvexPolyhedron}
  6495. */
  6496. this.convexPolyhedronRepresentation = null;
  6497. this.updateConvexPolyhedronRepresentation();
  6498. this.updateBoundingSphereRadius();
  6499. }
  6500. Box.prototype = new Shape();
  6501. Box.prototype.constructor = Box;
  6502. /**
  6503. * Updates the local convex polyhedron representation used for some collisions.
  6504. * @method updateConvexPolyhedronRepresentation
  6505. */
  6506. Box.prototype.updateConvexPolyhedronRepresentation = function(){
  6507. var sx = this.halfExtents.x;
  6508. var sy = this.halfExtents.y;
  6509. var sz = this.halfExtents.z;
  6510. var V = Vec3;
  6511. var vertices = [
  6512. new V(-sx,-sy,-sz),
  6513. new V( sx,-sy,-sz),
  6514. new V( sx, sy,-sz),
  6515. new V(-sx, sy,-sz),
  6516. new V(-sx,-sy, sz),
  6517. new V( sx,-sy, sz),
  6518. new V( sx, sy, sz),
  6519. new V(-sx, sy, sz)
  6520. ];
  6521. var indices = [
  6522. [3,2,1,0], // -z
  6523. [4,5,6,7], // +z
  6524. [5,4,0,1], // -y
  6525. [2,3,7,6], // +y
  6526. [0,4,7,3], // -x
  6527. [1,2,6,5], // +x
  6528. ];
  6529. var axes = [
  6530. new V(0, 0, 1),
  6531. new V(0, 1, 0),
  6532. new V(1, 0, 0)
  6533. ];
  6534. var h = new ConvexPolyhedron(vertices, indices);
  6535. this.convexPolyhedronRepresentation = h;
  6536. h.material = this.material;
  6537. };
  6538. /**
  6539. * @method calculateLocalInertia
  6540. * @param {Number} mass
  6541. * @param {Vec3} target
  6542. * @return {Vec3}
  6543. */
  6544. Box.prototype.calculateLocalInertia = function(mass,target){
  6545. target = target || new Vec3();
  6546. Box.calculateInertia(this.halfExtents, mass, target);
  6547. return target;
  6548. };
  6549. Box.calculateInertia = function(halfExtents,mass,target){
  6550. var e = halfExtents;
  6551. target.x = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.z*2*e.z );
  6552. target.y = 1.0 / 12.0 * mass * ( 2*e.x*2*e.x + 2*e.z*2*e.z );
  6553. target.z = 1.0 / 12.0 * mass * ( 2*e.y*2*e.y + 2*e.x*2*e.x );
  6554. };
  6555. /**
  6556. * Get the box 6 side normals
  6557. * @method getSideNormals
  6558. * @param {array} sixTargetVectors An array of 6 vectors, to store the resulting side normals in.
  6559. * @param {Quaternion} quat Orientation to apply to the normal vectors. If not provided, the vectors will be in respect to the local frame.
  6560. * @return {array}
  6561. */
  6562. Box.prototype.getSideNormals = function(sixTargetVectors,quat){
  6563. var sides = sixTargetVectors;
  6564. var ex = this.halfExtents;
  6565. sides[0].set( ex.x, 0, 0);
  6566. sides[1].set( 0, ex.y, 0);
  6567. sides[2].set( 0, 0, ex.z);
  6568. sides[3].set( -ex.x, 0, 0);
  6569. sides[4].set( 0, -ex.y, 0);
  6570. sides[5].set( 0, 0, -ex.z);
  6571. if(quat!==undefined){
  6572. for(var i=0; i!==sides.length; i++){
  6573. quat.vmult(sides[i],sides[i]);
  6574. }
  6575. }
  6576. return sides;
  6577. };
  6578. Box.prototype.volume = function(){
  6579. return 8.0 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z;
  6580. };
  6581. Box.prototype.updateBoundingSphereRadius = function(){
  6582. this.boundingSphereRadius = this.halfExtents.norm();
  6583. };
  6584. var worldCornerTempPos = new Vec3();
  6585. var worldCornerTempNeg = new Vec3();
  6586. Box.prototype.forEachWorldCorner = function(pos,quat,callback){
  6587. var e = this.halfExtents;
  6588. var corners = [[ e.x, e.y, e.z],
  6589. [ -e.x, e.y, e.z],
  6590. [ -e.x, -e.y, e.z],
  6591. [ -e.x, -e.y, -e.z],
  6592. [ e.x, -e.y, -e.z],
  6593. [ e.x, e.y, -e.z],
  6594. [ -e.x, e.y, -e.z],
  6595. [ e.x, -e.y, e.z]];
  6596. for(var i=0; i<corners.length; i++){
  6597. worldCornerTempPos.set(corners[i][0],corners[i][1],corners[i][2]);
  6598. quat.vmult(worldCornerTempPos,worldCornerTempPos);
  6599. pos.vadd(worldCornerTempPos,worldCornerTempPos);
  6600. callback(worldCornerTempPos.x,
  6601. worldCornerTempPos.y,
  6602. worldCornerTempPos.z);
  6603. }
  6604. };
  6605. var worldCornersTemp = [
  6606. new Vec3(),
  6607. new Vec3(),
  6608. new Vec3(),
  6609. new Vec3(),
  6610. new Vec3(),
  6611. new Vec3(),
  6612. new Vec3(),
  6613. new Vec3()
  6614. ];
  6615. Box.prototype.calculateWorldAABB = function(pos,quat,min,max){
  6616. var e = this.halfExtents;
  6617. worldCornersTemp[0].set(e.x, e.y, e.z);
  6618. worldCornersTemp[1].set(-e.x, e.y, e.z);
  6619. worldCornersTemp[2].set(-e.x, -e.y, e.z);
  6620. worldCornersTemp[3].set(-e.x, -e.y, -e.z);
  6621. worldCornersTemp[4].set(e.x, -e.y, -e.z);
  6622. worldCornersTemp[5].set(e.x, e.y, -e.z);
  6623. worldCornersTemp[6].set(-e.x, e.y, -e.z);
  6624. worldCornersTemp[7].set(e.x, -e.y, e.z);
  6625. var wc = worldCornersTemp[0];
  6626. quat.vmult(wc, wc);
  6627. pos.vadd(wc, wc);
  6628. max.copy(wc);
  6629. min.copy(wc);
  6630. for(var i=1; i<8; i++){
  6631. var wc = worldCornersTemp[i];
  6632. quat.vmult(wc, wc);
  6633. pos.vadd(wc, wc);
  6634. var x = wc.x;
  6635. var y = wc.y;
  6636. var z = wc.z;
  6637. if(x > max.x){
  6638. max.x = x;
  6639. }
  6640. if(y > max.y){
  6641. max.y = y;
  6642. }
  6643. if(z > max.z){
  6644. max.z = z;
  6645. }
  6646. if(x < min.x){
  6647. min.x = x;
  6648. }
  6649. if(y < min.y){
  6650. min.y = y;
  6651. }
  6652. if(z < min.z){
  6653. min.z = z;
  6654. }
  6655. }
  6656. // Get each axis max
  6657. // min.set(Infinity,Infinity,Infinity);
  6658. // max.set(-Infinity,-Infinity,-Infinity);
  6659. // this.forEachWorldCorner(pos,quat,function(x,y,z){
  6660. // if(x > max.x){
  6661. // max.x = x;
  6662. // }
  6663. // if(y > max.y){
  6664. // max.y = y;
  6665. // }
  6666. // if(z > max.z){
  6667. // max.z = z;
  6668. // }
  6669. // if(x < min.x){
  6670. // min.x = x;
  6671. // }
  6672. // if(y < min.y){
  6673. // min.y = y;
  6674. // }
  6675. // if(z < min.z){
  6676. // min.z = z;
  6677. // }
  6678. // });
  6679. };
  6680. },{"../math/Vec3":30,"./ConvexPolyhedron":38,"./Shape":43}],38:[function(_dereq_,module,exports){
  6681. module.exports = ConvexPolyhedron;
  6682. var Shape = _dereq_('./Shape');
  6683. var Vec3 = _dereq_('../math/Vec3');
  6684. var Quaternion = _dereq_('../math/Quaternion');
  6685. var Transform = _dereq_('../math/Transform');
  6686. /**
  6687. * A set of polygons describing a convex shape.
  6688. * @class ConvexPolyhedron
  6689. * @constructor
  6690. * @extends Shape
  6691. * @description The shape MUST be convex for the code to work properly. No polygons may be coplanar (contained
  6692. * in the same 3D plane), instead these should be merged into one polygon.
  6693. *
  6694. * @param {array} points An array of Vec3's
  6695. * @param {array} faces Array of integer arrays, describing which vertices that is included in each face.
  6696. *
  6697. * @author qiao / https://github.com/qiao (original author, see https://github.com/qiao/three.js/commit/85026f0c769e4000148a67d45a9e9b9c5108836f)
  6698. * @author schteppe / https://github.com/schteppe
  6699. * @see http://www.altdevblogaday.com/2011/05/13/contact-generation-between-3d-convex-meshes/
  6700. * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
  6701. *
  6702. * @todo Move the clipping functions to ContactGenerator?
  6703. * @todo Automatically merge coplanar polygons in constructor.
  6704. */
  6705. function ConvexPolyhedron(points, faces, uniqueAxes) {
  6706. var that = this;
  6707. Shape.call(this);
  6708. this.type = Shape.types.CONVEXPOLYHEDRON;
  6709. /**
  6710. * Array of Vec3
  6711. * @property vertices
  6712. * @type {Array}
  6713. */
  6714. this.vertices = points||[];
  6715. this.worldVertices = []; // World transformed version of .vertices
  6716. this.worldVerticesNeedsUpdate = true;
  6717. /**
  6718. * Array of integer arrays, indicating which vertices each face consists of
  6719. * @property faces
  6720. * @type {Array}
  6721. */
  6722. this.faces = faces||[];
  6723. /**
  6724. * Array of Vec3
  6725. * @property faceNormals
  6726. * @type {Array}
  6727. */
  6728. this.faceNormals = [];
  6729. this.computeNormals();
  6730. this.worldFaceNormalsNeedsUpdate = true;
  6731. this.worldFaceNormals = []; // World transformed version of .faceNormals
  6732. /**
  6733. * Array of Vec3
  6734. * @property uniqueEdges
  6735. * @type {Array}
  6736. */
  6737. this.uniqueEdges = [];
  6738. /**
  6739. * If given, these locally defined, normalized axes are the only ones being checked when doing separating axis check.
  6740. * @property {Array} uniqueAxes
  6741. */
  6742. this.uniqueAxes = uniqueAxes ? uniqueAxes.slice() : null;
  6743. this.computeEdges();
  6744. this.updateBoundingSphereRadius();
  6745. }
  6746. ConvexPolyhedron.prototype = new Shape();
  6747. ConvexPolyhedron.prototype.constructor = ConvexPolyhedron;
  6748. var computeEdges_tmpEdge = new Vec3();
  6749. /**
  6750. * Computes uniqueEdges
  6751. * @method computeEdges
  6752. */
  6753. ConvexPolyhedron.prototype.computeEdges = function(){
  6754. var faces = this.faces;
  6755. var vertices = this.vertices;
  6756. var nv = vertices.length;
  6757. var edges = this.uniqueEdges;
  6758. edges.length = 0;
  6759. var edge = computeEdges_tmpEdge;
  6760. for(var i=0; i !== faces.length; i++){
  6761. var face = faces[i];
  6762. var numVertices = face.length;
  6763. for(var j = 0; j !== numVertices; j++){
  6764. var k = ( j+1 ) % numVertices;
  6765. vertices[face[j]].vsub(vertices[face[k]], edge);
  6766. edge.normalize();
  6767. var found = false;
  6768. for(var p=0; p !== edges.length; p++){
  6769. if (edges[p].almostEquals(edge) || edges[p].almostEquals(edge)){
  6770. found = true;
  6771. break;
  6772. }
  6773. }
  6774. if (!found){
  6775. edges.push(edge.clone());
  6776. }
  6777. }
  6778. }
  6779. };
  6780. /**
  6781. * Compute the normals of the faces. Will reuse existing Vec3 objects in the .faceNormals array if they exist.
  6782. * @method computeNormals
  6783. */
  6784. ConvexPolyhedron.prototype.computeNormals = function(){
  6785. this.faceNormals.length = this.faces.length;
  6786. // Generate normals
  6787. for(var i=0; i<this.faces.length; i++){
  6788. // Check so all vertices exists for this face
  6789. for(var j=0; j<this.faces[i].length; j++){
  6790. if(!this.vertices[this.faces[i][j]]){
  6791. throw new Error("Vertex "+this.faces[i][j]+" not found!");
  6792. }
  6793. }
  6794. var n = this.faceNormals[i] || new Vec3();
  6795. this.getFaceNormal(i,n);
  6796. n.negate(n);
  6797. this.faceNormals[i] = n;
  6798. var vertex = this.vertices[this.faces[i][0]];
  6799. if(n.dot(vertex) < 0){
  6800. console.error(".faceNormals[" + i + "] = Vec3("+n.toString()+") looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.");
  6801. for(var j=0; j<this.faces[i].length; j++){
  6802. console.warn(".vertices["+this.faces[i][j]+"] = Vec3("+this.vertices[this.faces[i][j]].toString()+")");
  6803. }
  6804. }
  6805. }
  6806. };
  6807. /**
  6808. * Get face normal given 3 vertices
  6809. * @static
  6810. * @method getFaceNormal
  6811. * @param {Vec3} va
  6812. * @param {Vec3} vb
  6813. * @param {Vec3} vc
  6814. * @param {Vec3} target
  6815. */
  6816. var cb = new Vec3();
  6817. var ab = new Vec3();
  6818. ConvexPolyhedron.computeNormal = function ( va, vb, vc, target ) {
  6819. vb.vsub(va,ab);
  6820. vc.vsub(vb,cb);
  6821. cb.cross(ab,target);
  6822. if ( !target.isZero() ) {
  6823. target.normalize();
  6824. }
  6825. };
  6826. /**
  6827. * Compute the normal of a face from its vertices
  6828. * @method getFaceNormal
  6829. * @param {Number} i
  6830. * @param {Vec3} target
  6831. */
  6832. ConvexPolyhedron.prototype.getFaceNormal = function(i,target){
  6833. var f = this.faces[i];
  6834. var va = this.vertices[f[0]];
  6835. var vb = this.vertices[f[1]];
  6836. var vc = this.vertices[f[2]];
  6837. return ConvexPolyhedron.computeNormal(va,vb,vc,target);
  6838. };
  6839. /**
  6840. * @method clipAgainstHull
  6841. * @param {Vec3} posA
  6842. * @param {Quaternion} quatA
  6843. * @param {ConvexPolyhedron} hullB
  6844. * @param {Vec3} posB
  6845. * @param {Quaternion} quatB
  6846. * @param {Vec3} separatingNormal
  6847. * @param {Number} minDist Clamp distance
  6848. * @param {Number} maxDist
  6849. * @param {array} result The an array of contact point objects, see clipFaceAgainstHull
  6850. * @see http://bullet.googlecode.com/svn/trunk/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
  6851. */
  6852. var cah_WorldNormal = new Vec3();
  6853. ConvexPolyhedron.prototype.clipAgainstHull = function(posA,quatA,hullB,posB,quatB,separatingNormal,minDist,maxDist,result){
  6854. var WorldNormal = cah_WorldNormal;
  6855. var hullA = this;
  6856. var curMaxDist = maxDist;
  6857. var closestFaceB = -1;
  6858. var dmax = -Number.MAX_VALUE;
  6859. for(var face=0; face < hullB.faces.length; face++){
  6860. WorldNormal.copy(hullB.faceNormals[face]);
  6861. quatB.vmult(WorldNormal,WorldNormal);
  6862. //posB.vadd(WorldNormal,WorldNormal);
  6863. var d = WorldNormal.dot(separatingNormal);
  6864. if (d > dmax){
  6865. dmax = d;
  6866. closestFaceB = face;
  6867. }
  6868. }
  6869. var worldVertsB1 = [];
  6870. var polyB = hullB.faces[closestFaceB];
  6871. var numVertices = polyB.length;
  6872. for(var e0=0; e0<numVertices; e0++){
  6873. var b = hullB.vertices[polyB[e0]];
  6874. var worldb = new Vec3();
  6875. worldb.copy(b);
  6876. quatB.vmult(worldb,worldb);
  6877. posB.vadd(worldb,worldb);
  6878. worldVertsB1.push(worldb);
  6879. }
  6880. if (closestFaceB>=0){
  6881. this.clipFaceAgainstHull(separatingNormal,
  6882. posA,
  6883. quatA,
  6884. worldVertsB1,
  6885. minDist,
  6886. maxDist,
  6887. result);
  6888. }
  6889. };
  6890. /**
  6891. * Find the separating axis between this hull and another
  6892. * @method findSeparatingAxis
  6893. * @param {ConvexPolyhedron} hullB
  6894. * @param {Vec3} posA
  6895. * @param {Quaternion} quatA
  6896. * @param {Vec3} posB
  6897. * @param {Quaternion} quatB
  6898. * @param {Vec3} target The target vector to save the axis in
  6899. * @return {bool} Returns false if a separation is found, else true
  6900. */
  6901. var fsa_faceANormalWS3 = new Vec3(),
  6902. fsa_Worldnormal1 = new Vec3(),
  6903. fsa_deltaC = new Vec3(),
  6904. fsa_worldEdge0 = new Vec3(),
  6905. fsa_worldEdge1 = new Vec3(),
  6906. fsa_Cross = new Vec3();
  6907. ConvexPolyhedron.prototype.findSeparatingAxis = function(hullB,posA,quatA,posB,quatB,target, faceListA, faceListB){
  6908. var faceANormalWS3 = fsa_faceANormalWS3,
  6909. Worldnormal1 = fsa_Worldnormal1,
  6910. deltaC = fsa_deltaC,
  6911. worldEdge0 = fsa_worldEdge0,
  6912. worldEdge1 = fsa_worldEdge1,
  6913. Cross = fsa_Cross;
  6914. var dmin = Number.MAX_VALUE;
  6915. var hullA = this;
  6916. var curPlaneTests=0;
  6917. if(!hullA.uniqueAxes){
  6918. var numFacesA = faceListA ? faceListA.length : hullA.faces.length;
  6919. // Test face normals from hullA
  6920. for(var i=0; i<numFacesA; i++){
  6921. var fi = faceListA ? faceListA[i] : i;
  6922. // Get world face normal
  6923. faceANormalWS3.copy(hullA.faceNormals[fi]);
  6924. quatA.vmult(faceANormalWS3,faceANormalWS3);
  6925. var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
  6926. if(d===false){
  6927. return false;
  6928. }
  6929. if(d<dmin){
  6930. dmin = d;
  6931. target.copy(faceANormalWS3);
  6932. }
  6933. }
  6934. } else {
  6935. // Test unique axes
  6936. for(var i = 0; i !== hullA.uniqueAxes.length; i++){
  6937. // Get world axis
  6938. quatA.vmult(hullA.uniqueAxes[i],faceANormalWS3);
  6939. var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
  6940. if(d===false){
  6941. return false;
  6942. }
  6943. if(d<dmin){
  6944. dmin = d;
  6945. target.copy(faceANormalWS3);
  6946. }
  6947. }
  6948. }
  6949. if(!hullB.uniqueAxes){
  6950. // Test face normals from hullB
  6951. var numFacesB = faceListB ? faceListB.length : hullB.faces.length;
  6952. for(var i=0;i<numFacesB;i++){
  6953. var fi = faceListB ? faceListB[i] : i;
  6954. Worldnormal1.copy(hullB.faceNormals[fi]);
  6955. quatB.vmult(Worldnormal1,Worldnormal1);
  6956. curPlaneTests++;
  6957. var d = hullA.testSepAxis(Worldnormal1, hullB,posA,quatA,posB,quatB);
  6958. if(d===false){
  6959. return false;
  6960. }
  6961. if(d<dmin){
  6962. dmin = d;
  6963. target.copy(Worldnormal1);
  6964. }
  6965. }
  6966. } else {
  6967. // Test unique axes in B
  6968. for(var i = 0; i !== hullB.uniqueAxes.length; i++){
  6969. quatB.vmult(hullB.uniqueAxes[i],Worldnormal1);
  6970. curPlaneTests++;
  6971. var d = hullA.testSepAxis(Worldnormal1, hullB,posA,quatA,posB,quatB);
  6972. if(d===false){
  6973. return false;
  6974. }
  6975. if(d<dmin){
  6976. dmin = d;
  6977. target.copy(Worldnormal1);
  6978. }
  6979. }
  6980. }
  6981. // Test edges
  6982. for(var e0=0; e0 !== hullA.uniqueEdges.length; e0++){
  6983. // Get world edge
  6984. quatA.vmult(hullA.uniqueEdges[e0],worldEdge0);
  6985. for(var e1=0; e1 !== hullB.uniqueEdges.length; e1++){
  6986. // Get world edge 2
  6987. quatB.vmult(hullB.uniqueEdges[e1], worldEdge1);
  6988. worldEdge0.cross(worldEdge1,Cross);
  6989. if(!Cross.almostZero()){
  6990. Cross.normalize();
  6991. var dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB);
  6992. if(dist === false){
  6993. return false;
  6994. }
  6995. if(dist < dmin){
  6996. dmin = dist;
  6997. target.copy(Cross);
  6998. }
  6999. }
  7000. }
  7001. }
  7002. posB.vsub(posA,deltaC);
  7003. if((deltaC.dot(target))>0.0){
  7004. target.negate(target);
  7005. }
  7006. return true;
  7007. };
  7008. var maxminA=[], maxminB=[];
  7009. /**
  7010. * Test separating axis against two hulls. Both hulls are projected onto the axis and the overlap size is returned if there is one.
  7011. * @method testSepAxis
  7012. * @param {Vec3} axis
  7013. * @param {ConvexPolyhedron} hullB
  7014. * @param {Vec3} posA
  7015. * @param {Quaternion} quatA
  7016. * @param {Vec3} posB
  7017. * @param {Quaternion} quatB
  7018. * @return {number} The overlap depth, or FALSE if no penetration.
  7019. */
  7020. ConvexPolyhedron.prototype.testSepAxis = function(axis, hullB, posA, quatA, posB, quatB){
  7021. var hullA=this;
  7022. ConvexPolyhedron.project(hullA, axis, posA, quatA, maxminA);
  7023. ConvexPolyhedron.project(hullB, axis, posB, quatB, maxminB);
  7024. var maxA = maxminA[0];
  7025. var minA = maxminA[1];
  7026. var maxB = maxminB[0];
  7027. var minB = maxminB[1];
  7028. if(maxA<minB || maxB<minA){
  7029. return false; // Separated
  7030. }
  7031. var d0 = maxA - minB;
  7032. var d1 = maxB - minA;
  7033. var depth = d0<d1 ? d0:d1;
  7034. return depth;
  7035. };
  7036. var cli_aabbmin = new Vec3(),
  7037. cli_aabbmax = new Vec3();
  7038. /**
  7039. * @method calculateLocalInertia
  7040. * @param {Number} mass
  7041. * @param {Vec3} target
  7042. */
  7043. ConvexPolyhedron.prototype.calculateLocalInertia = function(mass,target){
  7044. // Approximate with box inertia
  7045. // Exact inertia calculation is overkill, but see http://geometrictools.com/Documentation/PolyhedralMassProperties.pdf for the correct way to do it
  7046. this.computeLocalAABB(cli_aabbmin,cli_aabbmax);
  7047. var x = cli_aabbmax.x - cli_aabbmin.x,
  7048. y = cli_aabbmax.y - cli_aabbmin.y,
  7049. z = cli_aabbmax.z - cli_aabbmin.z;
  7050. target.x = 1.0 / 12.0 * mass * ( 2*y*2*y + 2*z*2*z );
  7051. target.y = 1.0 / 12.0 * mass * ( 2*x*2*x + 2*z*2*z );
  7052. target.z = 1.0 / 12.0 * mass * ( 2*y*2*y + 2*x*2*x );
  7053. };
  7054. /**
  7055. * @method getPlaneConstantOfFace
  7056. * @param {Number} face_i Index of the face
  7057. * @return {Number}
  7058. */
  7059. ConvexPolyhedron.prototype.getPlaneConstantOfFace = function(face_i){
  7060. var f = this.faces[face_i];
  7061. var n = this.faceNormals[face_i];
  7062. var v = this.vertices[f[0]];
  7063. var c = -n.dot(v);
  7064. return c;
  7065. };
  7066. /**
  7067. * Clip a face against a hull.
  7068. * @method clipFaceAgainstHull
  7069. * @param {Vec3} separatingNormal
  7070. * @param {Vec3} posA
  7071. * @param {Quaternion} quatA
  7072. * @param {Array} worldVertsB1 An array of Vec3 with vertices in the world frame.
  7073. * @param {Number} minDist Distance clamping
  7074. * @param {Number} maxDist
  7075. * @param Array result Array to store resulting contact points in. Will be objects with properties: point, depth, normal. These are represented in world coordinates.
  7076. */
  7077. var cfah_faceANormalWS = new Vec3(),
  7078. cfah_edge0 = new Vec3(),
  7079. cfah_WorldEdge0 = new Vec3(),
  7080. cfah_worldPlaneAnormal1 = new Vec3(),
  7081. cfah_planeNormalWS1 = new Vec3(),
  7082. cfah_worldA1 = new Vec3(),
  7083. cfah_localPlaneNormal = new Vec3(),
  7084. cfah_planeNormalWS = new Vec3();
  7085. ConvexPolyhedron.prototype.clipFaceAgainstHull = function(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist,result){
  7086. var faceANormalWS = cfah_faceANormalWS,
  7087. edge0 = cfah_edge0,
  7088. WorldEdge0 = cfah_WorldEdge0,
  7089. worldPlaneAnormal1 = cfah_worldPlaneAnormal1,
  7090. planeNormalWS1 = cfah_planeNormalWS1,
  7091. worldA1 = cfah_worldA1,
  7092. localPlaneNormal = cfah_localPlaneNormal,
  7093. planeNormalWS = cfah_planeNormalWS;
  7094. var hullA = this;
  7095. var worldVertsB2 = [];
  7096. var pVtxIn = worldVertsB1;
  7097. var pVtxOut = worldVertsB2;
  7098. // Find the face with normal closest to the separating axis
  7099. var closestFaceA = -1;
  7100. var dmin = Number.MAX_VALUE;
  7101. for(var face=0; face<hullA.faces.length; face++){
  7102. faceANormalWS.copy(hullA.faceNormals[face]);
  7103. quatA.vmult(faceANormalWS,faceANormalWS);
  7104. //posA.vadd(faceANormalWS,faceANormalWS);
  7105. var d = faceANormalWS.dot(separatingNormal);
  7106. if (d < dmin){
  7107. dmin = d;
  7108. closestFaceA = face;
  7109. }
  7110. }
  7111. if (closestFaceA < 0){
  7112. // console.log("--- did not find any closest face... ---");
  7113. return;
  7114. }
  7115. //console.log("closest A: ",closestFaceA);
  7116. // Get the face and construct connected faces
  7117. var polyA = hullA.faces[closestFaceA];
  7118. polyA.connectedFaces = [];
  7119. for(var i=0; i<hullA.faces.length; i++){
  7120. for(var j=0; j<hullA.faces[i].length; j++){
  7121. if(polyA.indexOf(hullA.faces[i][j])!==-1 /* Sharing a vertex*/ && i!==closestFaceA /* Not the one we are looking for connections from */ && polyA.connectedFaces.indexOf(i)===-1 /* Not already added */ ){
  7122. polyA.connectedFaces.push(i);
  7123. }
  7124. }
  7125. }
  7126. // Clip the polygon to the back of the planes of all faces of hull A, that are adjacent to the witness face
  7127. var numContacts = pVtxIn.length;
  7128. var numVerticesA = polyA.length;
  7129. var res = [];
  7130. for(var e0=0; e0<numVerticesA; e0++){
  7131. var a = hullA.vertices[polyA[e0]];
  7132. var b = hullA.vertices[polyA[(e0+1)%numVerticesA]];
  7133. a.vsub(b,edge0);
  7134. WorldEdge0.copy(edge0);
  7135. quatA.vmult(WorldEdge0,WorldEdge0);
  7136. posA.vadd(WorldEdge0,WorldEdge0);
  7137. worldPlaneAnormal1.copy(this.faceNormals[closestFaceA]);//transA.getBasis()* btVector3(polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
  7138. quatA.vmult(worldPlaneAnormal1,worldPlaneAnormal1);
  7139. posA.vadd(worldPlaneAnormal1,worldPlaneAnormal1);
  7140. WorldEdge0.cross(worldPlaneAnormal1,planeNormalWS1);
  7141. planeNormalWS1.negate(planeNormalWS1);
  7142. worldA1.copy(a);
  7143. quatA.vmult(worldA1,worldA1);
  7144. posA.vadd(worldA1,worldA1);
  7145. var planeEqWS1 = -worldA1.dot(planeNormalWS1);
  7146. var planeEqWS;
  7147. if(true){
  7148. var otherFace = polyA.connectedFaces[e0];
  7149. localPlaneNormal.copy(this.faceNormals[otherFace]);
  7150. var localPlaneEq = this.getPlaneConstantOfFace(otherFace);
  7151. planeNormalWS.copy(localPlaneNormal);
  7152. quatA.vmult(planeNormalWS,planeNormalWS);
  7153. //posA.vadd(planeNormalWS,planeNormalWS);
  7154. var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
  7155. } else {
  7156. planeNormalWS.copy(planeNormalWS1);
  7157. planeEqWS = planeEqWS1;
  7158. }
  7159. // Clip face against our constructed plane
  7160. this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, planeEqWS);
  7161. // Throw away all clipped points, but save the reamining until next clip
  7162. while(pVtxIn.length){
  7163. pVtxIn.shift();
  7164. }
  7165. while(pVtxOut.length){
  7166. pVtxIn.push(pVtxOut.shift());
  7167. }
  7168. }
  7169. //console.log("Resulting points after clip:",pVtxIn);
  7170. // only keep contact points that are behind the witness face
  7171. localPlaneNormal.copy(this.faceNormals[closestFaceA]);
  7172. var localPlaneEq = this.getPlaneConstantOfFace(closestFaceA);
  7173. planeNormalWS.copy(localPlaneNormal);
  7174. quatA.vmult(planeNormalWS,planeNormalWS);
  7175. var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
  7176. for (var i=0; i<pVtxIn.length; i++){
  7177. var depth = planeNormalWS.dot(pVtxIn[i]) + planeEqWS; //???
  7178. /*console.log("depth calc from normal=",planeNormalWS.toString()," and constant "+planeEqWS+" and vertex ",pVtxIn[i].toString()," gives "+depth);*/
  7179. if (depth <=minDist){
  7180. console.log("clamped: depth="+depth+" to minDist="+(minDist+""));
  7181. depth = minDist;
  7182. }
  7183. if (depth <=maxDist){
  7184. var point = pVtxIn[i];
  7185. if(depth<=0){
  7186. /*console.log("Got contact point ",point.toString(),
  7187. ", depth=",depth,
  7188. "contact normal=",separatingNormal.toString(),
  7189. "plane",planeNormalWS.toString(),
  7190. "planeConstant",planeEqWS);*/
  7191. var p = {
  7192. point:point,
  7193. normal:planeNormalWS,
  7194. depth: depth,
  7195. };
  7196. result.push(p);
  7197. }
  7198. }
  7199. }
  7200. };
  7201. /**
  7202. * Clip a face in a hull against the back of a plane.
  7203. * @method clipFaceAgainstPlane
  7204. * @param {Array} inVertices
  7205. * @param {Array} outVertices
  7206. * @param {Vec3} planeNormal
  7207. * @param {Number} planeConstant The constant in the mathematical plane equation
  7208. */
  7209. ConvexPolyhedron.prototype.clipFaceAgainstPlane = function(inVertices,outVertices, planeNormal, planeConstant){
  7210. var n_dot_first, n_dot_last;
  7211. var numVerts = inVertices.length;
  7212. if(numVerts < 2){
  7213. return outVertices;
  7214. }
  7215. var firstVertex = inVertices[inVertices.length-1],
  7216. lastVertex = inVertices[0];
  7217. n_dot_first = planeNormal.dot(firstVertex) + planeConstant;
  7218. for(var vi = 0; vi < numVerts; vi++){
  7219. lastVertex = inVertices[vi];
  7220. n_dot_last = planeNormal.dot(lastVertex) + planeConstant;
  7221. if(n_dot_first < 0){
  7222. if(n_dot_last < 0){
  7223. // Start < 0, end < 0, so output lastVertex
  7224. var newv = new Vec3();
  7225. newv.copy(lastVertex);
  7226. outVertices.push(newv);
  7227. } else {
  7228. // Start < 0, end >= 0, so output intersection
  7229. var newv = new Vec3();
  7230. firstVertex.lerp(lastVertex,
  7231. n_dot_first / (n_dot_first - n_dot_last),
  7232. newv);
  7233. outVertices.push(newv);
  7234. }
  7235. } else {
  7236. if(n_dot_last<0){
  7237. // Start >= 0, end < 0 so output intersection and end
  7238. var newv = new Vec3();
  7239. firstVertex.lerp(lastVertex,
  7240. n_dot_first / (n_dot_first - n_dot_last),
  7241. newv);
  7242. outVertices.push(newv);
  7243. outVertices.push(lastVertex);
  7244. }
  7245. }
  7246. firstVertex = lastVertex;
  7247. n_dot_first = n_dot_last;
  7248. }
  7249. return outVertices;
  7250. };
  7251. // Updates .worldVertices and sets .worldVerticesNeedsUpdate to false.
  7252. ConvexPolyhedron.prototype.computeWorldVertices = function(position,quat){
  7253. var N = this.vertices.length;
  7254. while(this.worldVertices.length < N){
  7255. this.worldVertices.push( new Vec3() );
  7256. }
  7257. var verts = this.vertices,
  7258. worldVerts = this.worldVertices;
  7259. for(var i=0; i!==N; i++){
  7260. quat.vmult( verts[i] , worldVerts[i] );
  7261. position.vadd( worldVerts[i] , worldVerts[i] );
  7262. }
  7263. this.worldVerticesNeedsUpdate = false;
  7264. };
  7265. var computeLocalAABB_worldVert = new Vec3();
  7266. ConvexPolyhedron.prototype.computeLocalAABB = function(aabbmin,aabbmax){
  7267. var n = this.vertices.length,
  7268. vertices = this.vertices,
  7269. worldVert = computeLocalAABB_worldVert;
  7270. aabbmin.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  7271. aabbmax.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
  7272. for(var i=0; i<n; i++){
  7273. var v = vertices[i];
  7274. if (v.x < aabbmin.x){
  7275. aabbmin.x = v.x;
  7276. } else if(v.x > aabbmax.x){
  7277. aabbmax.x = v.x;
  7278. }
  7279. if (v.y < aabbmin.y){
  7280. aabbmin.y = v.y;
  7281. } else if(v.y > aabbmax.y){
  7282. aabbmax.y = v.y;
  7283. }
  7284. if (v.z < aabbmin.z){
  7285. aabbmin.z = v.z;
  7286. } else if(v.z > aabbmax.z){
  7287. aabbmax.z = v.z;
  7288. }
  7289. }
  7290. };
  7291. /**
  7292. * Updates .worldVertices and sets .worldVerticesNeedsUpdate to false.
  7293. * @method computeWorldFaceNormals
  7294. * @param {Quaternion} quat
  7295. */
  7296. ConvexPolyhedron.prototype.computeWorldFaceNormals = function(quat){
  7297. var N = this.faceNormals.length;
  7298. while(this.worldFaceNormals.length < N){
  7299. this.worldFaceNormals.push( new Vec3() );
  7300. }
  7301. var normals = this.faceNormals,
  7302. worldNormals = this.worldFaceNormals;
  7303. for(var i=0; i!==N; i++){
  7304. quat.vmult( normals[i] , worldNormals[i] );
  7305. }
  7306. this.worldFaceNormalsNeedsUpdate = false;
  7307. };
  7308. /**
  7309. * @method updateBoundingSphereRadius
  7310. */
  7311. ConvexPolyhedron.prototype.updateBoundingSphereRadius = function(){
  7312. // Assume points are distributed with local (0,0,0) as center
  7313. var max2 = 0;
  7314. var verts = this.vertices;
  7315. for(var i=0, N=verts.length; i!==N; i++) {
  7316. var norm2 = verts[i].norm2();
  7317. if(norm2 > max2){
  7318. max2 = norm2;
  7319. }
  7320. }
  7321. this.boundingSphereRadius = Math.sqrt(max2);
  7322. };
  7323. var tempWorldVertex = new Vec3();
  7324. /**
  7325. * @method calculateWorldAABB
  7326. * @param {Vec3} pos
  7327. * @param {Quaternion} quat
  7328. * @param {Vec3} min
  7329. * @param {Vec3} max
  7330. */
  7331. ConvexPolyhedron.prototype.calculateWorldAABB = function(pos,quat,min,max){
  7332. var n = this.vertices.length, verts = this.vertices;
  7333. var minx,miny,minz,maxx,maxy,maxz;
  7334. for(var i=0; i<n; i++){
  7335. tempWorldVertex.copy(verts[i]);
  7336. quat.vmult(tempWorldVertex,tempWorldVertex);
  7337. pos.vadd(tempWorldVertex,tempWorldVertex);
  7338. var v = tempWorldVertex;
  7339. if (v.x < minx || minx===undefined){
  7340. minx = v.x;
  7341. } else if(v.x > maxx || maxx===undefined){
  7342. maxx = v.x;
  7343. }
  7344. if (v.y < miny || miny===undefined){
  7345. miny = v.y;
  7346. } else if(v.y > maxy || maxy===undefined){
  7347. maxy = v.y;
  7348. }
  7349. if (v.z < minz || minz===undefined){
  7350. minz = v.z;
  7351. } else if(v.z > maxz || maxz===undefined){
  7352. maxz = v.z;
  7353. }
  7354. }
  7355. min.set(minx,miny,minz);
  7356. max.set(maxx,maxy,maxz);
  7357. };
  7358. /**
  7359. * Get approximate convex volume
  7360. * @method volume
  7361. * @return {Number}
  7362. */
  7363. ConvexPolyhedron.prototype.volume = function(){
  7364. return 4.0 * Math.PI * this.boundingSphereRadius / 3.0;
  7365. };
  7366. /**
  7367. * Get an average of all the vertices positions
  7368. * @method getAveragePointLocal
  7369. * @param {Vec3} target
  7370. * @return {Vec3}
  7371. */
  7372. ConvexPolyhedron.prototype.getAveragePointLocal = function(target){
  7373. target = target || new Vec3();
  7374. var n = this.vertices.length,
  7375. verts = this.vertices;
  7376. for(var i=0; i<n; i++){
  7377. target.vadd(verts[i],target);
  7378. }
  7379. target.mult(1/n,target);
  7380. return target;
  7381. };
  7382. /**
  7383. * Transform all local points. Will change the .vertices
  7384. * @method transformAllPoints
  7385. * @param {Vec3} offset
  7386. * @param {Quaternion} quat
  7387. */
  7388. ConvexPolyhedron.prototype.transformAllPoints = function(offset,quat){
  7389. var n = this.vertices.length,
  7390. verts = this.vertices;
  7391. // Apply rotation
  7392. if(quat){
  7393. // Rotate vertices
  7394. for(var i=0; i<n; i++){
  7395. var v = verts[i];
  7396. quat.vmult(v,v);
  7397. }
  7398. // Rotate face normals
  7399. for(var i=0; i<this.faceNormals.length; i++){
  7400. var v = this.faceNormals[i];
  7401. quat.vmult(v,v);
  7402. }
  7403. /*
  7404. // Rotate edges
  7405. for(var i=0; i<this.uniqueEdges.length; i++){
  7406. var v = this.uniqueEdges[i];
  7407. quat.vmult(v,v);
  7408. }*/
  7409. }
  7410. // Apply offset
  7411. if(offset){
  7412. for(var i=0; i<n; i++){
  7413. var v = verts[i];
  7414. v.vadd(offset,v);
  7415. }
  7416. }
  7417. };
  7418. /**
  7419. * Checks whether p is inside the polyhedra. Must be in local coords. The point lies outside of the convex hull of the other points if and only if the direction of all the vectors from it to those other points are on less than one half of a sphere around it.
  7420. * @method pointIsInside
  7421. * @param {Vec3} p A point given in local coordinates
  7422. * @return {Boolean}
  7423. */
  7424. var ConvexPolyhedron_pointIsInside = new Vec3();
  7425. var ConvexPolyhedron_vToP = new Vec3();
  7426. var ConvexPolyhedron_vToPointInside = new Vec3();
  7427. ConvexPolyhedron.prototype.pointIsInside = function(p){
  7428. var n = this.vertices.length,
  7429. verts = this.vertices,
  7430. faces = this.faces,
  7431. normals = this.faceNormals;
  7432. var positiveResult = null;
  7433. var N = this.faces.length;
  7434. var pointInside = ConvexPolyhedron_pointIsInside;
  7435. this.getAveragePointLocal(pointInside);
  7436. for(var i=0; i<N; i++){
  7437. var numVertices = this.faces[i].length;
  7438. var n = normals[i];
  7439. var v = verts[faces[i][0]]; // We only need one point in the face
  7440. // This dot product determines which side of the edge the point is
  7441. var vToP = ConvexPolyhedron_vToP;
  7442. p.vsub(v,vToP);
  7443. var r1 = n.dot(vToP);
  7444. var vToPointInside = ConvexPolyhedron_vToPointInside;
  7445. pointInside.vsub(v,vToPointInside);
  7446. var r2 = n.dot(vToPointInside);
  7447. if((r1<0 && r2>0) || (r1>0 && r2<0)){
  7448. return false; // Encountered some other sign. Exit.
  7449. } else {
  7450. }
  7451. }
  7452. // If we got here, all dot products were of the same sign.
  7453. return positiveResult ? 1 : -1;
  7454. };
  7455. /**
  7456. * Get max and min dot product of a convex hull at position (pos,quat) projected onto an axis. Results are saved in the array maxmin.
  7457. * @static
  7458. * @method project
  7459. * @param {ConvexPolyhedron} hull
  7460. * @param {Vec3} axis
  7461. * @param {Vec3} pos
  7462. * @param {Quaternion} quat
  7463. * @param {array} result result[0] and result[1] will be set to maximum and minimum, respectively.
  7464. */
  7465. var project_worldVertex = new Vec3();
  7466. var project_localAxis = new Vec3();
  7467. var project_localOrigin = new Vec3();
  7468. ConvexPolyhedron.project = function(hull, axis, pos, quat, result){
  7469. var n = hull.vertices.length,
  7470. worldVertex = project_worldVertex,
  7471. localAxis = project_localAxis,
  7472. max = 0,
  7473. min = 0,
  7474. localOrigin = project_localOrigin,
  7475. vs = hull.vertices;
  7476. localOrigin.setZero();
  7477. // Transform the axis to local
  7478. Transform.vectorToLocalFrame(pos, quat, axis, localAxis);
  7479. Transform.pointToLocalFrame(pos, quat, localOrigin, localOrigin);
  7480. var add = localOrigin.dot(localAxis);
  7481. min = max = vs[0].dot(localAxis);
  7482. for(var i = 1; i < n; i++){
  7483. var val = vs[i].dot(localAxis);
  7484. if(val > max){
  7485. max = val;
  7486. }
  7487. if(val < min){
  7488. min = val;
  7489. }
  7490. }
  7491. min -= add;
  7492. max -= add;
  7493. if(min > max){
  7494. // Inconsistent - swap
  7495. var temp = min;
  7496. min = max;
  7497. max = temp;
  7498. }
  7499. // Output
  7500. result[0] = max;
  7501. result[1] = min;
  7502. };
  7503. },{"../math/Quaternion":28,"../math/Transform":29,"../math/Vec3":30,"./Shape":43}],39:[function(_dereq_,module,exports){
  7504. module.exports = Cylinder;
  7505. var Shape = _dereq_('./Shape');
  7506. var Vec3 = _dereq_('../math/Vec3');
  7507. var Quaternion = _dereq_('../math/Quaternion');
  7508. var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
  7509. /**
  7510. * @class Cylinder
  7511. * @constructor
  7512. * @extends ConvexPolyhedron
  7513. * @author schteppe / https://github.com/schteppe
  7514. * @param {Number} radiusTop
  7515. * @param {Number} radiusBottom
  7516. * @param {Number} height
  7517. * @param {Number} numSegments The number of segments to build the cylinder out of
  7518. */
  7519. function Cylinder( radiusTop, radiusBottom, height , numSegments ) {
  7520. var N = numSegments,
  7521. verts = [],
  7522. axes = [],
  7523. faces = [],
  7524. bottomface = [],
  7525. topface = [],
  7526. cos = Math.cos,
  7527. sin = Math.sin;
  7528. // First bottom point
  7529. verts.push(new Vec3(radiusBottom*cos(0),
  7530. radiusBottom*sin(0),
  7531. -height*0.5));
  7532. bottomface.push(0);
  7533. // First top point
  7534. verts.push(new Vec3(radiusTop*cos(0),
  7535. radiusTop*sin(0),
  7536. height*0.5));
  7537. topface.push(1);
  7538. for(var i=0; i<N; i++){
  7539. var theta = 2*Math.PI/N * (i+1);
  7540. var thetaN = 2*Math.PI/N * (i+0.5);
  7541. if(i<N-1){
  7542. // Bottom
  7543. verts.push(new Vec3(radiusBottom*cos(theta),
  7544. radiusBottom*sin(theta),
  7545. -height*0.5));
  7546. bottomface.push(2*i+2);
  7547. // Top
  7548. verts.push(new Vec3(radiusTop*cos(theta),
  7549. radiusTop*sin(theta),
  7550. height*0.5));
  7551. topface.push(2*i+3);
  7552. // Face
  7553. faces.push([2*i+2, 2*i+3, 2*i+1,2*i]);
  7554. } else {
  7555. faces.push([0,1, 2*i+1, 2*i]); // Connect
  7556. }
  7557. // Axis: we can cut off half of them if we have even number of segments
  7558. if(N % 2 === 1 || i < N / 2){
  7559. axes.push(new Vec3(cos(thetaN), sin(thetaN), 0));
  7560. }
  7561. }
  7562. faces.push(topface);
  7563. axes.push(new Vec3(0,0,1));
  7564. // Reorder bottom face
  7565. var temp = [];
  7566. for(var i=0; i<bottomface.length; i++){
  7567. temp.push(bottomface[bottomface.length - i - 1]);
  7568. }
  7569. faces.push(temp);
  7570. this.type = Shape.types.CONVEXPOLYHEDRON;
  7571. ConvexPolyhedron.call( this, verts, faces, axes );
  7572. }
  7573. Cylinder.prototype = new ConvexPolyhedron();
  7574. },{"../math/Quaternion":28,"../math/Vec3":30,"./ConvexPolyhedron":38,"./Shape":43}],40:[function(_dereq_,module,exports){
  7575. var Shape = _dereq_('./Shape');
  7576. var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
  7577. var Vec3 = _dereq_('../math/Vec3');
  7578. var Utils = _dereq_('../utils/Utils');
  7579. module.exports = Heightfield;
  7580. /**
  7581. * Heightfield shape class. Height data is given as an array. These data points are spread out evenly with a given distance.
  7582. * @class Heightfield
  7583. * @extends Shape
  7584. * @constructor
  7585. * @param {Array} data An array of Y values that will be used to construct the terrain.
  7586. * @param {object} options
  7587. * @param {Number} [options.minValue] Minimum value of the data points in the data array. Will be computed automatically if not given.
  7588. * @param {Number} [options.maxValue] Maximum value.
  7589. * @param {Number} [options.elementSize=0.1] World spacing between the data points in X direction.
  7590. * @todo Should be possible to use along all axes, not just y
  7591. *
  7592. * @example
  7593. * // Generate some height data (y-values).
  7594. * var data = [];
  7595. * for(var i = 0; i < 1000; i++){
  7596. * var y = 0.5 * Math.cos(0.2 * i);
  7597. * data.push(y);
  7598. * }
  7599. *
  7600. * // Create the heightfield shape
  7601. * var heightfieldShape = new Heightfield(data, {
  7602. * elementSize: 1 // Distance between the data points in X and Y directions
  7603. * });
  7604. * var heightfieldBody = new Body();
  7605. * heightfieldBody.addShape(heightfieldShape);
  7606. * world.addBody(heightfieldBody);
  7607. */
  7608. function Heightfield(data, options){
  7609. options = Utils.defaults(options, {
  7610. maxValue : null,
  7611. minValue : null,
  7612. elementSize : 1
  7613. });
  7614. /**
  7615. * An array of numbers, or height values, that are spread out along the x axis.
  7616. * @property {array} data
  7617. */
  7618. this.data = data;
  7619. /**
  7620. * Max value of the data
  7621. * @property {number} maxValue
  7622. */
  7623. this.maxValue = options.maxValue;
  7624. /**
  7625. * Max value of the data
  7626. * @property {number} minValue
  7627. */
  7628. this.minValue = options.minValue;
  7629. /**
  7630. * The width of each element
  7631. * @property {number} elementSize
  7632. * @todo elementSizeX and Y
  7633. */
  7634. this.elementSize = options.elementSize;
  7635. if(options.minValue === null){
  7636. this.updateMinValue();
  7637. }
  7638. if(options.maxValue === null){
  7639. this.updateMaxValue();
  7640. }
  7641. this.cacheEnabled = true;
  7642. Shape.call(this);
  7643. this.pillarConvex = new ConvexPolyhedron();
  7644. this.pillarOffset = new Vec3();
  7645. this.type = Shape.types.HEIGHTFIELD;
  7646. this.updateBoundingSphereRadius();
  7647. // "i_j_isUpper" => { convex: ..., offset: ... }
  7648. // for example:
  7649. // _cachedPillars["0_2_1"]
  7650. this._cachedPillars = {};
  7651. }
  7652. Heightfield.prototype = new Shape();
  7653. /**
  7654. * Call whenever you change the data array.
  7655. * @method update
  7656. */
  7657. Heightfield.prototype.update = function(){
  7658. this._cachedPillars = {};
  7659. };
  7660. /**
  7661. * Update the .minValue property
  7662. * @method updateMinValue
  7663. */
  7664. Heightfield.prototype.updateMinValue = function(){
  7665. var data = this.data;
  7666. var minValue = data[0][0];
  7667. for(var i=0; i !== data.length; i++){
  7668. for(var j=0; j !== data[i].length; j++){
  7669. var v = data[i][j];
  7670. if(v < minValue){
  7671. minValue = v;
  7672. }
  7673. }
  7674. }
  7675. this.minValue = minValue;
  7676. };
  7677. /**
  7678. * Update the .maxValue property
  7679. * @method updateMaxValue
  7680. */
  7681. Heightfield.prototype.updateMaxValue = function(){
  7682. var data = this.data;
  7683. var maxValue = data[0][0];
  7684. for(var i=0; i !== data.length; i++){
  7685. for(var j=0; j !== data[i].length; j++){
  7686. var v = data[i][j];
  7687. if(v > maxValue){
  7688. maxValue = v;
  7689. }
  7690. }
  7691. }
  7692. this.maxValue = maxValue;
  7693. };
  7694. /**
  7695. * Set the height value at an index. Don't forget to update maxValue and minValue after you're done.
  7696. * @method setHeightValueAtIndex
  7697. * @param {integer} xi
  7698. * @param {integer} yi
  7699. * @param {number} value
  7700. */
  7701. Heightfield.prototype.setHeightValueAtIndex = function(xi, yi, value){
  7702. var data = this.data;
  7703. data[xi][yi] = value;
  7704. // Invalidate cache
  7705. this.clearCachedConvexTrianglePillar(xi, yi, false);
  7706. if(xi > 0){
  7707. this.clearCachedConvexTrianglePillar(xi - 1, yi, true);
  7708. this.clearCachedConvexTrianglePillar(xi - 1, yi, false);
  7709. }
  7710. if(yi > 0){
  7711. this.clearCachedConvexTrianglePillar(xi, yi - 1, true);
  7712. this.clearCachedConvexTrianglePillar(xi, yi - 1, false);
  7713. }
  7714. if(yi > 0 && xi > 0){
  7715. this.clearCachedConvexTrianglePillar(xi - 1, yi - 1, true);
  7716. }
  7717. };
  7718. /**
  7719. * Get max/min in a rectangle in the matrix data
  7720. * @method getRectMinMax
  7721. * @param {integer} iMinX
  7722. * @param {integer} iMinY
  7723. * @param {integer} iMaxX
  7724. * @param {integer} iMaxY
  7725. * @param {array} [result] An array to store the results in.
  7726. * @return {array} The result array, if it was passed in. Minimum will be at position 0 and max at 1.
  7727. */
  7728. Heightfield.prototype.getRectMinMax = function (iMinX, iMinY, iMaxX, iMaxY, result) {
  7729. result = result || [];
  7730. // Get max and min of the data
  7731. var data = this.data,
  7732. max = this.minValue; // Set first value
  7733. for(var i = iMinX; i <= iMaxX; i++){
  7734. for(var j = iMinY; j <= iMaxY; j++){
  7735. var height = data[i][j];
  7736. if(height > max){
  7737. max = height;
  7738. }
  7739. }
  7740. }
  7741. result[0] = this.minValue;
  7742. result[1] = max;
  7743. };
  7744. /**
  7745. * Get the index of a local position on the heightfield. The indexes indicate the rectangles, so if your terrain is made of N x N height data points, you will have rectangle indexes ranging from 0 to N-1.
  7746. * @method getIndexOfPosition
  7747. * @param {number} x
  7748. * @param {number} y
  7749. * @param {array} result Two-element array
  7750. * @param {boolean} clamp If the position should be clamped to the heightfield edge.
  7751. * @return {boolean}
  7752. */
  7753. Heightfield.prototype.getIndexOfPosition = function (x, y, result, clamp) {
  7754. // Get the index of the data points to test against
  7755. var w = this.elementSize;
  7756. var data = this.data;
  7757. var xi = Math.floor(x / w);
  7758. var yi = Math.floor(y / w);
  7759. result[0] = xi;
  7760. result[1] = yi;
  7761. if(clamp){
  7762. // Clamp index to edges
  7763. if(xi < 0){ xi = 0; }
  7764. if(yi < 0){ yi = 0; }
  7765. if(xi >= data.length - 1){ xi = data.length - 1; }
  7766. if(yi >= data[0].length - 1){ yi = data[0].length - 1; }
  7767. }
  7768. // Bail out if we are out of the terrain
  7769. if(xi < 0 || yi < 0 || xi >= data.length-1 || yi >= data[0].length-1){
  7770. return false;
  7771. }
  7772. return true;
  7773. };
  7774. Heightfield.prototype.getHeightAt = function(x, y, edgeClamp){
  7775. var idx = [];
  7776. this.getIndexOfPosition(x, y, idx, edgeClamp);
  7777. // TODO: get upper or lower triangle, then use barycentric interpolation to get the height in the triangle.
  7778. var minmax = [];
  7779. this.getRectMinMax(idx[0], idx[1] + 1, idx[0], idx[1] + 1, minmax);
  7780. return (minmax[0] + minmax[1]) / 2; // average
  7781. };
  7782. Heightfield.prototype.getCacheConvexTrianglePillarKey = function(xi, yi, getUpperTriangle){
  7783. return xi + '_' + yi + '_' + (getUpperTriangle ? 1 : 0);
  7784. };
  7785. Heightfield.prototype.getCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle){
  7786. return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
  7787. };
  7788. Heightfield.prototype.setCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle, convex, offset){
  7789. this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)] = {
  7790. convex: convex,
  7791. offset: offset
  7792. };
  7793. };
  7794. Heightfield.prototype.clearCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle){
  7795. delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
  7796. };
  7797. /**
  7798. * Get a triangle in the terrain in the form of a triangular convex shape.
  7799. * @method getConvexTrianglePillar
  7800. * @param {integer} i
  7801. * @param {integer} j
  7802. * @param {boolean} getUpperTriangle
  7803. */
  7804. Heightfield.prototype.getConvexTrianglePillar = function(xi, yi, getUpperTriangle){
  7805. var result = this.pillarConvex;
  7806. var offsetResult = this.pillarOffset;
  7807. if(this.cacheEnabled){
  7808. var data = this.getCachedConvexTrianglePillar(xi, yi, getUpperTriangle);
  7809. if(data){
  7810. this.pillarConvex = data.convex;
  7811. this.pillarOffset = data.offset;
  7812. return;
  7813. }
  7814. result = new ConvexPolyhedron();
  7815. offsetResult = new Vec3();
  7816. this.pillarConvex = result;
  7817. this.pillarOffset = offsetResult;
  7818. }
  7819. var data = this.data;
  7820. var elementSize = this.elementSize;
  7821. var faces = result.faces;
  7822. // Reuse verts if possible
  7823. result.vertices.length = 6;
  7824. for (var i = 0; i < 6; i++) {
  7825. if(!result.vertices[i]){
  7826. result.vertices[i] = new Vec3();
  7827. }
  7828. }
  7829. // Reuse faces if possible
  7830. faces.length = 5;
  7831. for (var i = 0; i < 5; i++) {
  7832. if(!faces[i]){
  7833. faces[i] = [];
  7834. }
  7835. }
  7836. var verts = result.vertices;
  7837. var h = (Math.min(
  7838. data[xi][yi],
  7839. data[xi+1][yi],
  7840. data[xi][yi+1],
  7841. data[xi+1][yi+1]
  7842. ) - this.minValue ) / 2 + this.minValue;
  7843. if (!getUpperTriangle) {
  7844. // Center of the triangle pillar - all polygons are given relative to this one
  7845. offsetResult.set(
  7846. (xi + 0.25) * elementSize, // sort of center of a triangle
  7847. (yi + 0.25) * elementSize,
  7848. h // vertical center
  7849. );
  7850. // Top triangle verts
  7851. verts[0].set(
  7852. -0.25 * elementSize,
  7853. -0.25 * elementSize,
  7854. data[xi][yi] - h
  7855. );
  7856. verts[1].set(
  7857. 0.75 * elementSize,
  7858. -0.25 * elementSize,
  7859. data[xi + 1][yi] - h
  7860. );
  7861. verts[2].set(
  7862. -0.25 * elementSize,
  7863. 0.75 * elementSize,
  7864. data[xi][yi + 1] - h
  7865. );
  7866. // bottom triangle verts
  7867. verts[3].set(
  7868. -0.25 * elementSize,
  7869. -0.25 * elementSize,
  7870. -h-1
  7871. );
  7872. verts[4].set(
  7873. 0.75 * elementSize,
  7874. -0.25 * elementSize,
  7875. -h-1
  7876. );
  7877. verts[5].set(
  7878. -0.25 * elementSize,
  7879. 0.75 * elementSize,
  7880. -h-1
  7881. );
  7882. // top triangle
  7883. faces[0][0] = 0;
  7884. faces[0][1] = 1;
  7885. faces[0][2] = 2;
  7886. // bottom triangle
  7887. faces[1][0] = 5;
  7888. faces[1][1] = 4;
  7889. faces[1][2] = 3;
  7890. // -x facing quad
  7891. faces[2][0] = 0;
  7892. faces[2][1] = 2;
  7893. faces[2][2] = 5;
  7894. faces[2][3] = 3;
  7895. // -y facing quad
  7896. faces[3][0] = 1;
  7897. faces[3][1] = 0;
  7898. faces[3][2] = 3;
  7899. faces[3][3] = 4;
  7900. // +xy facing quad
  7901. faces[4][0] = 4;
  7902. faces[4][1] = 5;
  7903. faces[4][2] = 2;
  7904. faces[4][3] = 1;
  7905. } else {
  7906. // Center of the triangle pillar - all polygons are given relative to this one
  7907. offsetResult.set(
  7908. (xi + 0.75) * elementSize, // sort of center of a triangle
  7909. (yi + 0.75) * elementSize,
  7910. h // vertical center
  7911. );
  7912. // Top triangle verts
  7913. verts[0].set(
  7914. 0.25 * elementSize,
  7915. 0.25 * elementSize,
  7916. data[xi + 1][yi + 1] - h
  7917. );
  7918. verts[1].set(
  7919. -0.75 * elementSize,
  7920. 0.25 * elementSize,
  7921. data[xi][yi + 1] - h
  7922. );
  7923. verts[2].set(
  7924. 0.25 * elementSize,
  7925. -0.75 * elementSize,
  7926. data[xi + 1][yi] - h
  7927. );
  7928. // bottom triangle verts
  7929. verts[3].set(
  7930. 0.25 * elementSize,
  7931. 0.25 * elementSize,
  7932. - h-1
  7933. );
  7934. verts[4].set(
  7935. -0.75 * elementSize,
  7936. 0.25 * elementSize,
  7937. - h-1
  7938. );
  7939. verts[5].set(
  7940. 0.25 * elementSize,
  7941. -0.75 * elementSize,
  7942. - h-1
  7943. );
  7944. // Top triangle
  7945. faces[0][0] = 0;
  7946. faces[0][1] = 1;
  7947. faces[0][2] = 2;
  7948. // bottom triangle
  7949. faces[1][0] = 5;
  7950. faces[1][1] = 4;
  7951. faces[1][2] = 3;
  7952. // +x facing quad
  7953. faces[2][0] = 2;
  7954. faces[2][1] = 5;
  7955. faces[2][2] = 3;
  7956. faces[2][3] = 0;
  7957. // +y facing quad
  7958. faces[3][0] = 3;
  7959. faces[3][1] = 4;
  7960. faces[3][2] = 1;
  7961. faces[3][3] = 0;
  7962. // -xy facing quad
  7963. faces[4][0] = 1;
  7964. faces[4][1] = 4;
  7965. faces[4][2] = 5;
  7966. faces[4][3] = 2;
  7967. }
  7968. result.computeNormals();
  7969. result.computeEdges();
  7970. result.updateBoundingSphereRadius();
  7971. this.setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, result, offsetResult);
  7972. };
  7973. Heightfield.prototype.calculateLocalInertia = function(mass, target){
  7974. target = target || new Vec3();
  7975. target.set(0, 0, 0);
  7976. return target;
  7977. };
  7978. Heightfield.prototype.volume = function(){
  7979. return Number.MAX_VALUE; // The terrain is infinite
  7980. };
  7981. Heightfield.prototype.calculateWorldAABB = function(pos, quat, min, max){
  7982. // TODO: do it properly
  7983. min.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
  7984. max.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
  7985. };
  7986. Heightfield.prototype.updateBoundingSphereRadius = function(){
  7987. // Use the bounding box of the min/max values
  7988. var data = this.data,
  7989. s = this.elementSize;
  7990. this.boundingSphereRadius = new Vec3(data.length * s, data[0].length * s, Math.max(Math.abs(this.maxValue), Math.abs(this.minValue))).norm();
  7991. };
  7992. },{"../math/Vec3":30,"../utils/Utils":53,"./ConvexPolyhedron":38,"./Shape":43}],41:[function(_dereq_,module,exports){
  7993. module.exports = Particle;
  7994. var Shape = _dereq_('./Shape');
  7995. var Vec3 = _dereq_('../math/Vec3');
  7996. /**
  7997. * Particle shape.
  7998. * @class Particle
  7999. * @constructor
  8000. * @author schteppe
  8001. * @extends Shape
  8002. */
  8003. function Particle(){
  8004. Shape.call(this);
  8005. this.type = Shape.types.PARTICLE;
  8006. }
  8007. Particle.prototype = new Shape();
  8008. Particle.prototype.constructor = Particle;
  8009. /**
  8010. * @method calculateLocalInertia
  8011. * @param {Number} mass
  8012. * @param {Vec3} target
  8013. * @return {Vec3}
  8014. */
  8015. Particle.prototype.calculateLocalInertia = function(mass,target){
  8016. target = target || new Vec3();
  8017. target.set(0, 0, 0);
  8018. return target;
  8019. };
  8020. Particle.prototype.volume = function(){
  8021. return 0;
  8022. };
  8023. Particle.prototype.updateBoundingSphereRadius = function(){
  8024. this.boundingSphereRadius = 0;
  8025. };
  8026. Particle.prototype.calculateWorldAABB = function(pos,quat,min,max){
  8027. // Get each axis max
  8028. min.copy(pos);
  8029. max.copy(pos);
  8030. };
  8031. },{"../math/Vec3":30,"./Shape":43}],42:[function(_dereq_,module,exports){
  8032. module.exports = Plane;
  8033. var Shape = _dereq_('./Shape');
  8034. var Vec3 = _dereq_('../math/Vec3');
  8035. /**
  8036. * A plane, facing in the Z direction. The plane has its surface at z=0 and everything below z=0 is assumed to be solid plane. To make the plane face in some other direction than z, you must put it inside a RigidBody and rotate that body. See the demos.
  8037. * @class Plane
  8038. * @constructor
  8039. * @extends Shape
  8040. * @author schteppe
  8041. */
  8042. function Plane(){
  8043. Shape.call(this);
  8044. this.type = Shape.types.PLANE;
  8045. // World oriented normal
  8046. this.worldNormal = new Vec3();
  8047. this.worldNormalNeedsUpdate = true;
  8048. this.boundingSphereRadius = Number.MAX_VALUE;
  8049. }
  8050. Plane.prototype = new Shape();
  8051. Plane.prototype.constructor = Plane;
  8052. Plane.prototype.computeWorldNormal = function(quat){
  8053. var n = this.worldNormal;
  8054. n.set(0,0,1);
  8055. quat.vmult(n,n);
  8056. this.worldNormalNeedsUpdate = false;
  8057. };
  8058. Plane.prototype.calculateLocalInertia = function(mass,target){
  8059. target = target || new Vec3();
  8060. return target;
  8061. };
  8062. Plane.prototype.volume = function(){
  8063. return Number.MAX_VALUE; // The plane is infinite...
  8064. };
  8065. var tempNormal = new Vec3();
  8066. Plane.prototype.calculateWorldAABB = function(pos, quat, min, max){
  8067. // The plane AABB is infinite, except if the normal is pointing along any axis
  8068. tempNormal.set(0,0,1); // Default plane normal is z
  8069. quat.vmult(tempNormal,tempNormal);
  8070. var maxVal = Number.MAX_VALUE;
  8071. min.set(-maxVal, -maxVal, -maxVal);
  8072. max.set(maxVal, maxVal, maxVal);
  8073. if(tempNormal.x === 1){ max.x = pos.x; }
  8074. if(tempNormal.y === 1){ max.y = pos.y; }
  8075. if(tempNormal.z === 1){ max.z = pos.z; }
  8076. if(tempNormal.x === -1){ min.x = pos.x; }
  8077. if(tempNormal.y === -1){ min.y = pos.y; }
  8078. if(tempNormal.z === -1){ min.z = pos.z; }
  8079. };
  8080. Plane.prototype.updateBoundingSphereRadius = function(){
  8081. this.boundingSphereRadius = Number.MAX_VALUE;
  8082. };
  8083. },{"../math/Vec3":30,"./Shape":43}],43:[function(_dereq_,module,exports){
  8084. module.exports = Shape;
  8085. var Shape = _dereq_('./Shape');
  8086. var Vec3 = _dereq_('../math/Vec3');
  8087. var Quaternion = _dereq_('../math/Quaternion');
  8088. var Material = _dereq_('../material/Material');
  8089. /**
  8090. * Base class for shapes
  8091. * @class Shape
  8092. * @constructor
  8093. * @author schteppe
  8094. * @todo Should have a mechanism for caching bounding sphere radius instead of calculating it each time
  8095. */
  8096. function Shape(){
  8097. /**
  8098. * Identifyer of the Shape.
  8099. * @property {number} id
  8100. */
  8101. this.id = Shape.idCounter++;
  8102. /**
  8103. * The type of this shape. Must be set to an int > 0 by subclasses.
  8104. * @property type
  8105. * @type {Number}
  8106. * @see Shape.types
  8107. */
  8108. this.type = 0;
  8109. /**
  8110. * The local bounding sphere radius of this shape.
  8111. * @property {Number} boundingSphereRadius
  8112. */
  8113. this.boundingSphereRadius = 0;
  8114. /**
  8115. * Whether to produce contact forces when in contact with other bodies. Note that contacts will be generated, but they will be disabled.
  8116. * @property {boolean} collisionResponse
  8117. */
  8118. this.collisionResponse = true;
  8119. /**
  8120. * @property {Material} material
  8121. */
  8122. this.material = null;
  8123. }
  8124. Shape.prototype.constructor = Shape;
  8125. /**
  8126. * Computes the bounding sphere radius. The result is stored in the property .boundingSphereRadius
  8127. * @method updateBoundingSphereRadius
  8128. * @return {Number}
  8129. */
  8130. Shape.prototype.updateBoundingSphereRadius = function(){
  8131. throw "computeBoundingSphereRadius() not implemented for shape type "+this.type;
  8132. };
  8133. /**
  8134. * Get the volume of this shape
  8135. * @method volume
  8136. * @return {Number}
  8137. */
  8138. Shape.prototype.volume = function(){
  8139. throw "volume() not implemented for shape type "+this.type;
  8140. };
  8141. /**
  8142. * Calculates the inertia in the local frame for this shape.
  8143. * @method calculateLocalInertia
  8144. * @return {Vec3}
  8145. * @see http://en.wikipedia.org/wiki/List_of_moments_of_inertia
  8146. */
  8147. Shape.prototype.calculateLocalInertia = function(mass,target){
  8148. throw "calculateLocalInertia() not implemented for shape type "+this.type;
  8149. };
  8150. Shape.idCounter = 0;
  8151. /**
  8152. * The available shape types.
  8153. * @static
  8154. * @property types
  8155. * @type {Object}
  8156. */
  8157. Shape.types = {
  8158. SPHERE:1,
  8159. PLANE:2,
  8160. BOX:4,
  8161. COMPOUND:8,
  8162. CONVEXPOLYHEDRON:16,
  8163. HEIGHTFIELD:32,
  8164. PARTICLE:64,
  8165. CYLINDER:128,
  8166. TRIMESH:256
  8167. };
  8168. },{"../material/Material":25,"../math/Quaternion":28,"../math/Vec3":30,"./Shape":43}],44:[function(_dereq_,module,exports){
  8169. module.exports = Sphere;
  8170. var Shape = _dereq_('./Shape');
  8171. var Vec3 = _dereq_('../math/Vec3');
  8172. /**
  8173. * Spherical shape
  8174. * @class Sphere
  8175. * @constructor
  8176. * @extends Shape
  8177. * @param {Number} radius The radius of the sphere, a non-negative number.
  8178. * @author schteppe / http://github.com/schteppe
  8179. */
  8180. function Sphere(radius){
  8181. Shape.call(this);
  8182. /**
  8183. * @property {Number} radius
  8184. */
  8185. this.radius = radius!==undefined ? Number(radius) : 1.0;
  8186. this.type = Shape.types.SPHERE;
  8187. if(this.radius < 0){
  8188. throw new Error('The sphere radius cannot be negative.');
  8189. }
  8190. this.updateBoundingSphereRadius();
  8191. }
  8192. Sphere.prototype = new Shape();
  8193. Sphere.prototype.constructor = Sphere;
  8194. Sphere.prototype.calculateLocalInertia = function(mass,target){
  8195. target = target || new Vec3();
  8196. var I = 2.0*mass*this.radius*this.radius/5.0;
  8197. target.x = I;
  8198. target.y = I;
  8199. target.z = I;
  8200. return target;
  8201. };
  8202. Sphere.prototype.volume = function(){
  8203. return 4.0 * Math.PI * this.radius / 3.0;
  8204. };
  8205. Sphere.prototype.updateBoundingSphereRadius = function(){
  8206. this.boundingSphereRadius = this.radius;
  8207. };
  8208. Sphere.prototype.calculateWorldAABB = function(pos,quat,min,max){
  8209. var r = this.radius;
  8210. var axes = ['x','y','z'];
  8211. for(var i=0; i<axes.length; i++){
  8212. var ax = axes[i];
  8213. min[ax] = pos[ax] - r;
  8214. max[ax] = pos[ax] + r;
  8215. }
  8216. };
  8217. },{"../math/Vec3":30,"./Shape":43}],45:[function(_dereq_,module,exports){
  8218. module.exports = Trimesh;
  8219. var Shape = _dereq_('./Shape');
  8220. var Vec3 = _dereq_('../math/Vec3');
  8221. var Quaternion = _dereq_('../math/Quaternion');
  8222. var Transform = _dereq_('../math/Transform');
  8223. var AABB = _dereq_('../collision/AABB');
  8224. var Octree = _dereq_('../utils/Octree');
  8225. /**
  8226. * @class Trimesh
  8227. * @constructor
  8228. * @param {array} vertices
  8229. * @param {array} indices
  8230. * @extends Shape
  8231. * @example
  8232. * // How to make a mesh with a single triangle
  8233. * var vertices = [
  8234. * 0, 0, 0, // vertex 0
  8235. * 1, 0, 0, // vertex 1
  8236. * 0, 1, 0 // vertex 2
  8237. * ];
  8238. * var indices = [
  8239. * 0, 1, 2 // triangle 0
  8240. * ];
  8241. * var trimeshShape = new Trimesh(vertices, indices);
  8242. */
  8243. function Trimesh(vertices, indices) {
  8244. Shape.call(this);
  8245. this.type = Shape.types.TRIMESH;
  8246. /**
  8247. * @property vertices
  8248. * @type {Array}
  8249. */
  8250. this.vertices = new Float32Array(vertices);
  8251. /**
  8252. * Array of integers, indicating which vertices each triangle consists of. The length of this array is thus 3 times the number of triangles.
  8253. * @property indices
  8254. * @type {Array}
  8255. */
  8256. this.indices = new Int16Array(indices);
  8257. /**
  8258. * The normals data.
  8259. * @property normals
  8260. * @type {Array}
  8261. */
  8262. this.normals = new Float32Array(indices.length);
  8263. /**
  8264. * The local AABB of the mesh.
  8265. * @property aabb
  8266. * @type {Array}
  8267. */
  8268. this.aabb = new AABB();
  8269. /**
  8270. * References to vertex pairs, making up all unique edges in the trimesh.
  8271. * @property {array} edges
  8272. */
  8273. this.edges = null;
  8274. /**
  8275. * Local scaling of the mesh. Use .setScale() to set it.
  8276. * @property {Vec3} scale
  8277. */
  8278. this.scale = new Vec3(1, 1, 1);
  8279. /**
  8280. * The indexed triangles. Use .updateTree() to update it.
  8281. * @property {Octree} tree
  8282. */
  8283. this.tree = new Octree();
  8284. this.updateEdges();
  8285. this.updateNormals();
  8286. this.updateAABB();
  8287. this.updateBoundingSphereRadius();
  8288. this.updateTree();
  8289. }
  8290. Trimesh.prototype = new Shape();
  8291. Trimesh.prototype.constructor = Trimesh;
  8292. var computeNormals_n = new Vec3();
  8293. /**
  8294. * @method updateTree
  8295. */
  8296. Trimesh.prototype.updateTree = function(){
  8297. var tree = this.tree;
  8298. tree.reset();
  8299. tree.aabb.copy(this.aabb);
  8300. var scale = this.scale; // The local mesh AABB is scaled, but the octree AABB should be unscaled
  8301. tree.aabb.lowerBound.x *= 1 / scale.x;
  8302. tree.aabb.lowerBound.y *= 1 / scale.y;
  8303. tree.aabb.lowerBound.z *= 1 / scale.z;
  8304. tree.aabb.upperBound.x *= 1 / scale.x;
  8305. tree.aabb.upperBound.y *= 1 / scale.y;
  8306. tree.aabb.upperBound.z *= 1 / scale.z;
  8307. // Insert all triangles
  8308. var triangleAABB = new AABB();
  8309. var a = new Vec3();
  8310. var b = new Vec3();
  8311. var c = new Vec3();
  8312. var points = [a, b, c];
  8313. for (var i = 0; i < this.indices.length / 3; i++) {
  8314. //this.getTriangleVertices(i, a, b, c);
  8315. // Get unscaled triangle verts
  8316. var i3 = i * 3;
  8317. this._getUnscaledVertex(this.indices[i3], a);
  8318. this._getUnscaledVertex(this.indices[i3 + 1], b);
  8319. this._getUnscaledVertex(this.indices[i3 + 2], c);
  8320. triangleAABB.setFromPoints(points);
  8321. tree.insert(triangleAABB, i);
  8322. }
  8323. tree.removeEmptyNodes();
  8324. };
  8325. var unscaledAABB = new AABB();
  8326. /**
  8327. * Get triangles in a local AABB from the trimesh.
  8328. * @method getTrianglesInAABB
  8329. * @param {AABB} aabb
  8330. * @param {array} result An array of integers, referencing the queried triangles.
  8331. */
  8332. Trimesh.prototype.getTrianglesInAABB = function(aabb, result){
  8333. unscaledAABB.copy(aabb);
  8334. // Scale it to local
  8335. var scale = this.scale;
  8336. var isx = scale.x;
  8337. var isy = scale.y;
  8338. var isz = scale.z;
  8339. var l = unscaledAABB.lowerBound;
  8340. var u = unscaledAABB.upperBound;
  8341. l.x /= isx;
  8342. l.y /= isy;
  8343. l.z /= isz;
  8344. u.x /= isx;
  8345. u.y /= isy;
  8346. u.z /= isz;
  8347. return this.tree.aabbQuery(unscaledAABB, result);
  8348. };
  8349. /**
  8350. * @method setScale
  8351. * @param {Vec3} scale
  8352. */
  8353. Trimesh.prototype.setScale = function(scale){
  8354. var wasUniform = this.scale.x === this.scale.y === this.scale.z;
  8355. var isUniform = scale.x === scale.y === scale.z;
  8356. if(!(wasUniform && isUniform)){
  8357. // Non-uniform scaling. Need to update normals.
  8358. this.updateNormals();
  8359. }
  8360. this.scale.copy(scale);
  8361. this.updateAABB();
  8362. this.updateBoundingSphereRadius();
  8363. };
  8364. /**
  8365. * Compute the normals of the faces. Will save in the .normals array.
  8366. * @method updateNormals
  8367. */
  8368. Trimesh.prototype.updateNormals = function(){
  8369. var n = computeNormals_n;
  8370. // Generate normals
  8371. var normals = this.normals;
  8372. for(var i=0; i < this.indices.length / 3; i++){
  8373. var i3 = i * 3;
  8374. var a = this.indices[i3],
  8375. b = this.indices[i3 + 1],
  8376. c = this.indices[i3 + 2];
  8377. this.getVertex(a, va);
  8378. this.getVertex(b, vb);
  8379. this.getVertex(c, vc);
  8380. Trimesh.computeNormal(vb, va, vc, n);
  8381. normals[i3] = n.x;
  8382. normals[i3 + 1] = n.y;
  8383. normals[i3 + 2] = n.z;
  8384. }
  8385. };
  8386. /**
  8387. * Update the .edges property
  8388. * @method updateEdges
  8389. */
  8390. Trimesh.prototype.updateEdges = function(){
  8391. var edges = {};
  8392. var add = function(indexA, indexB){
  8393. var key = a < b ? a + '_' + b : b + '_' + a;
  8394. edges[key] = true;
  8395. };
  8396. for(var i=0; i < this.indices.length / 3; i++){
  8397. var i3 = i * 3;
  8398. var a = this.indices[i3],
  8399. b = this.indices[i3 + 1],
  8400. c = this.indices[i3 + 2];
  8401. add(a,b);
  8402. add(b,c);
  8403. add(c,a);
  8404. }
  8405. var keys = Object.keys(edges);
  8406. this.edges = new Int16Array(keys.length * 2);
  8407. for (var i = 0; i < keys.length; i++) {
  8408. var indices = keys[i].split('_');
  8409. this.edges[2 * i] = parseInt(indices[0], 10);
  8410. this.edges[2 * i + 1] = parseInt(indices[1], 10);
  8411. }
  8412. };
  8413. /**
  8414. * Get an edge vertex
  8415. * @method getEdgeVertex
  8416. * @param {number} edgeIndex
  8417. * @param {number} firstOrSecond 0 or 1, depending on which one of the vertices you need.
  8418. * @param {Vec3} vertexStore Where to store the result
  8419. */
  8420. Trimesh.prototype.getEdgeVertex = function(edgeIndex, firstOrSecond, vertexStore){
  8421. var vertexIndex = this.edges[edgeIndex * 2 + (firstOrSecond ? 1 : 0)];
  8422. this.getVertex(vertexIndex, vertexStore);
  8423. };
  8424. var getEdgeVector_va = new Vec3();
  8425. var getEdgeVector_vb = new Vec3();
  8426. /**
  8427. * Get a vector along an edge.
  8428. * @method getEdgeVector
  8429. * @param {number} edgeIndex
  8430. * @param {Vec3} vectorStore
  8431. */
  8432. Trimesh.prototype.getEdgeVector = function(edgeIndex, vectorStore){
  8433. var va = getEdgeVector_va;
  8434. var vb = getEdgeVector_vb;
  8435. this.getEdgeVertex(edgeIndex, 0, va);
  8436. this.getEdgeVertex(edgeIndex, 1, vb);
  8437. vb.vsub(va, vectorStore);
  8438. };
  8439. /**
  8440. * Get face normal given 3 vertices
  8441. * @static
  8442. * @method computeNormal
  8443. * @param {Vec3} va
  8444. * @param {Vec3} vb
  8445. * @param {Vec3} vc
  8446. * @param {Vec3} target
  8447. */
  8448. var cb = new Vec3();
  8449. var ab = new Vec3();
  8450. Trimesh.computeNormal = function ( va, vb, vc, target ) {
  8451. vb.vsub(va,ab);
  8452. vc.vsub(vb,cb);
  8453. cb.cross(ab,target);
  8454. if ( !target.isZero() ) {
  8455. target.normalize();
  8456. }
  8457. };
  8458. var va = new Vec3();
  8459. var vb = new Vec3();
  8460. var vc = new Vec3();
  8461. /**
  8462. * Get vertex i.
  8463. * @method getVertex
  8464. * @param {number} i
  8465. * @param {Vec3} out
  8466. * @return {Vec3} The "out" vector object
  8467. */
  8468. Trimesh.prototype.getVertex = function(i, out){
  8469. var scale = this.scale;
  8470. this._getUnscaledVertex(i, out);
  8471. out.x *= scale.x;
  8472. out.y *= scale.y;
  8473. out.z *= scale.z;
  8474. return out;
  8475. };
  8476. /**
  8477. * Get raw vertex i
  8478. * @private
  8479. * @method _getUnscaledVertex
  8480. * @param {number} i
  8481. * @param {Vec3} out
  8482. * @return {Vec3} The "out" vector object
  8483. */
  8484. Trimesh.prototype._getUnscaledVertex = function(i, out){
  8485. var i3 = i * 3;
  8486. var vertices = this.vertices;
  8487. return out.set(
  8488. vertices[i3],
  8489. vertices[i3 + 1],
  8490. vertices[i3 + 2]
  8491. );
  8492. };
  8493. /**
  8494. * Get a vertex from the trimesh,transformed by the given position and quaternion.
  8495. * @method getWorldVertex
  8496. * @param {number} i
  8497. * @param {Vec3} pos
  8498. * @param {Quaternion} quat
  8499. * @param {Vec3} out
  8500. * @return {Vec3} The "out" vector object
  8501. */
  8502. Trimesh.prototype.getWorldVertex = function(i, pos, quat, out){
  8503. this.getVertex(i, out);
  8504. Transform.pointToWorldFrame(pos, quat, out, out);
  8505. return out;
  8506. };
  8507. /**
  8508. * Get the three vertices for triangle i.
  8509. * @method getTriangleVertices
  8510. * @param {number} i
  8511. * @param {Vec3} a
  8512. * @param {Vec3} b
  8513. * @param {Vec3} c
  8514. */
  8515. Trimesh.prototype.getTriangleVertices = function(i, a, b, c){
  8516. var i3 = i * 3;
  8517. this.getVertex(this.indices[i3], a);
  8518. this.getVertex(this.indices[i3 + 1], b);
  8519. this.getVertex(this.indices[i3 + 2], c);
  8520. };
  8521. /**
  8522. * Compute the normal of triangle i.
  8523. * @method getNormal
  8524. * @param {Number} i
  8525. * @param {Vec3} target
  8526. * @return {Vec3} The "target" vector object
  8527. */
  8528. Trimesh.prototype.getNormal = function(i, target){
  8529. var i3 = i * 3;
  8530. return target.set(
  8531. this.normals[i3],
  8532. this.normals[i3 + 1],
  8533. this.normals[i3 + 2]
  8534. );
  8535. };
  8536. var cli_aabb = new AABB();
  8537. /**
  8538. * @method calculateLocalInertia
  8539. * @param {Number} mass
  8540. * @param {Vec3} target
  8541. * @return {Vec3} The "target" vector object
  8542. */
  8543. Trimesh.prototype.calculateLocalInertia = function(mass,target){
  8544. // Approximate with box inertia
  8545. // Exact inertia calculation is overkill, but see http://geometrictools.com/Documentation/PolyhedralMassProperties.pdf for the correct way to do it
  8546. this.computeLocalAABB(cli_aabb);
  8547. var x = cli_aabb.upperBound.x - cli_aabb.lowerBound.x,
  8548. y = cli_aabb.upperBound.y - cli_aabb.lowerBound.y,
  8549. z = cli_aabb.upperBound.z - cli_aabb.lowerBound.z;
  8550. return target.set(
  8551. 1.0 / 12.0 * mass * ( 2*y*2*y + 2*z*2*z ),
  8552. 1.0 / 12.0 * mass * ( 2*x*2*x + 2*z*2*z ),
  8553. 1.0 / 12.0 * mass * ( 2*y*2*y + 2*x*2*x )
  8554. );
  8555. };
  8556. var computeLocalAABB_worldVert = new Vec3();
  8557. /**
  8558. * Compute the local AABB for the trimesh
  8559. * @method computeLocalAABB
  8560. * @param {AABB} aabb
  8561. */
  8562. Trimesh.prototype.computeLocalAABB = function(aabb){
  8563. var l = aabb.lowerBound,
  8564. u = aabb.upperBound,
  8565. n = this.vertices.length,
  8566. vertices = this.vertices,
  8567. v = computeLocalAABB_worldVert;
  8568. this.getVertex(0, v);
  8569. l.copy(v);
  8570. u.copy(v);
  8571. for(var i=0; i !== n; i++){
  8572. this.getVertex(i, v);
  8573. if(v.x < l.x){
  8574. l.x = v.x;
  8575. } else if(v.x > u.x){
  8576. u.x = v.x;
  8577. }
  8578. if(v.y < l.y){
  8579. l.y = v.y;
  8580. } else if(v.y > u.y){
  8581. u.y = v.y;
  8582. }
  8583. if(v.z < l.z){
  8584. l.z = v.z;
  8585. } else if(v.z > u.z){
  8586. u.z = v.z;
  8587. }
  8588. }
  8589. };
  8590. /**
  8591. * Update the .aabb property
  8592. * @method updateAABB
  8593. */
  8594. Trimesh.prototype.updateAABB = function(){
  8595. this.computeLocalAABB(this.aabb);
  8596. };
  8597. /**
  8598. * Will update the .boundingSphereRadius property
  8599. * @method updateBoundingSphereRadius
  8600. */
  8601. Trimesh.prototype.updateBoundingSphereRadius = function(){
  8602. // Assume points are distributed with local (0,0,0) as center
  8603. var max2 = 0;
  8604. var vertices = this.vertices;
  8605. var v = new Vec3();
  8606. for(var i=0, N=vertices.length / 3; i !== N; i++) {
  8607. this.getVertex(i, v);
  8608. var norm2 = v.norm2();
  8609. if(norm2 > max2){
  8610. max2 = norm2;
  8611. }
  8612. }
  8613. this.boundingSphereRadius = Math.sqrt(max2);
  8614. };
  8615. var tempWorldVertex = new Vec3();
  8616. var calculateWorldAABB_frame = new Transform();
  8617. var calculateWorldAABB_aabb = new AABB();
  8618. /**
  8619. * @method calculateWorldAABB
  8620. * @param {Vec3} pos
  8621. * @param {Quaternion} quat
  8622. * @param {Vec3} min
  8623. * @param {Vec3} max
  8624. */
  8625. Trimesh.prototype.calculateWorldAABB = function(pos,quat,min,max){
  8626. /*
  8627. var n = this.vertices.length / 3,
  8628. verts = this.vertices;
  8629. var minx,miny,minz,maxx,maxy,maxz;
  8630. var v = tempWorldVertex;
  8631. for(var i=0; i<n; i++){
  8632. this.getVertex(i, v);
  8633. quat.vmult(v, v);
  8634. pos.vadd(v, v);
  8635. if (v.x < minx || minx===undefined){
  8636. minx = v.x;
  8637. } else if(v.x > maxx || maxx===undefined){
  8638. maxx = v.x;
  8639. }
  8640. if (v.y < miny || miny===undefined){
  8641. miny = v.y;
  8642. } else if(v.y > maxy || maxy===undefined){
  8643. maxy = v.y;
  8644. }
  8645. if (v.z < minz || minz===undefined){
  8646. minz = v.z;
  8647. } else if(v.z > maxz || maxz===undefined){
  8648. maxz = v.z;
  8649. }
  8650. }
  8651. min.set(minx,miny,minz);
  8652. max.set(maxx,maxy,maxz);
  8653. */
  8654. // Faster approximation using local AABB
  8655. var frame = calculateWorldAABB_frame;
  8656. var result = calculateWorldAABB_aabb;
  8657. frame.position = pos;
  8658. frame.quaternion = quat;
  8659. this.aabb.toWorldFrame(frame, result);
  8660. min.copy(result.lowerBound);
  8661. max.copy(result.upperBound);
  8662. };
  8663. /**
  8664. * Get approximate volume
  8665. * @method volume
  8666. * @return {Number}
  8667. */
  8668. Trimesh.prototype.volume = function(){
  8669. return 4.0 * Math.PI * this.boundingSphereRadius / 3.0;
  8670. };
  8671. /**
  8672. * Create a Trimesh instance, shaped as a torus.
  8673. * @static
  8674. * @method createTorus
  8675. * @param {number} [radius=1]
  8676. * @param {number} [tube=0.5]
  8677. * @param {number} [radialSegments=8]
  8678. * @param {number} [tubularSegments=6]
  8679. * @param {number} [arc=6.283185307179586]
  8680. * @return {Trimesh} A torus
  8681. */
  8682. Trimesh.createTorus = function (radius, tube, radialSegments, tubularSegments, arc) {
  8683. radius = radius || 1;
  8684. tube = tube || 0.5;
  8685. radialSegments = radialSegments || 8;
  8686. tubularSegments = tubularSegments || 6;
  8687. arc = arc || Math.PI * 2;
  8688. var vertices = [];
  8689. var indices = [];
  8690. for ( var j = 0; j <= radialSegments; j ++ ) {
  8691. for ( var i = 0; i <= tubularSegments; i ++ ) {
  8692. var u = i / tubularSegments * arc;
  8693. var v = j / radialSegments * Math.PI * 2;
  8694. var x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
  8695. var y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
  8696. var z = tube * Math.sin( v );
  8697. vertices.push( x, y, z );
  8698. }
  8699. }
  8700. for ( var j = 1; j <= radialSegments; j ++ ) {
  8701. for ( var i = 1; i <= tubularSegments; i ++ ) {
  8702. var a = ( tubularSegments + 1 ) * j + i - 1;
  8703. var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
  8704. var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
  8705. var d = ( tubularSegments + 1 ) * j + i;
  8706. indices.push(a, b, d);
  8707. indices.push(b, c, d);
  8708. }
  8709. }
  8710. return new Trimesh(vertices, indices);
  8711. };
  8712. },{"../collision/AABB":3,"../math/Quaternion":28,"../math/Transform":29,"../math/Vec3":30,"../utils/Octree":50,"./Shape":43}],46:[function(_dereq_,module,exports){
  8713. module.exports = GSSolver;
  8714. var Vec3 = _dereq_('../math/Vec3');
  8715. var Quaternion = _dereq_('../math/Quaternion');
  8716. var Solver = _dereq_('./Solver');
  8717. /**
  8718. * Constraint equation Gauss-Seidel solver.
  8719. * @class GSSolver
  8720. * @constructor
  8721. * @todo The spook parameters should be specified for each constraint, not globally.
  8722. * @author schteppe / https://github.com/schteppe
  8723. * @see https://www8.cs.umu.se/kurser/5DV058/VT09/lectures/spooknotes.pdf
  8724. * @extends Solver
  8725. */
  8726. function GSSolver(){
  8727. Solver.call(this);
  8728. /**
  8729. * The number of solver iterations determines quality of the constraints in the world. The more iterations, the more correct simulation. More iterations need more computations though. If you have a large gravity force in your world, you will need more iterations.
  8730. * @property iterations
  8731. * @type {Number}
  8732. * @todo write more about solver and iterations in the wiki
  8733. */
  8734. this.iterations = 10;
  8735. /**
  8736. * When tolerance is reached, the system is assumed to be converged.
  8737. * @property tolerance
  8738. * @type {Number}
  8739. */
  8740. this.tolerance = 1e-7;
  8741. }
  8742. GSSolver.prototype = new Solver();
  8743. var GSSolver_solve_lambda = []; // Just temporary number holders that we want to reuse each solve.
  8744. var GSSolver_solve_invCs = [];
  8745. var GSSolver_solve_Bs = [];
  8746. GSSolver.prototype.solve = function(dt,world){
  8747. var iter = 0,
  8748. maxIter = this.iterations,
  8749. tolSquared = this.tolerance*this.tolerance,
  8750. equations = this.equations,
  8751. Neq = equations.length,
  8752. bodies = world.bodies,
  8753. Nbodies = bodies.length,
  8754. h = dt,
  8755. q, B, invC, deltalambda, deltalambdaTot, GWlambda, lambdaj;
  8756. // Update solve mass
  8757. if(Neq !== 0){
  8758. for(var i=0; i!==Nbodies; i++){
  8759. bodies[i].updateSolveMassProperties();
  8760. }
  8761. }
  8762. // Things that does not change during iteration can be computed once
  8763. var invCs = GSSolver_solve_invCs,
  8764. Bs = GSSolver_solve_Bs,
  8765. lambda = GSSolver_solve_lambda;
  8766. invCs.length = Neq;
  8767. Bs.length = Neq;
  8768. lambda.length = Neq;
  8769. for(var i=0; i!==Neq; i++){
  8770. var c = equations[i];
  8771. lambda[i] = 0.0;
  8772. Bs[i] = c.computeB(h);
  8773. invCs[i] = 1.0 / c.computeC();
  8774. }
  8775. if(Neq !== 0){
  8776. // Reset vlambda
  8777. for(var i=0; i!==Nbodies; i++){
  8778. var b=bodies[i],
  8779. vlambda=b.vlambda,
  8780. wlambda=b.wlambda;
  8781. vlambda.set(0,0,0);
  8782. if(wlambda){
  8783. wlambda.set(0,0,0);
  8784. }
  8785. }
  8786. // Iterate over equations
  8787. for(iter=0; iter!==maxIter; iter++){
  8788. // Accumulate the total error for each iteration.
  8789. deltalambdaTot = 0.0;
  8790. for(var j=0; j!==Neq; j++){
  8791. var c = equations[j];
  8792. // Compute iteration
  8793. B = Bs[j];
  8794. invC = invCs[j];
  8795. lambdaj = lambda[j];
  8796. GWlambda = c.computeGWlambda();
  8797. deltalambda = invC * ( B - GWlambda - c.eps * lambdaj );
  8798. // Clamp if we are not within the min/max interval
  8799. if(lambdaj + deltalambda < c.minForce){
  8800. deltalambda = c.minForce - lambdaj;
  8801. } else if(lambdaj + deltalambda > c.maxForce){
  8802. deltalambda = c.maxForce - lambdaj;
  8803. }
  8804. lambda[j] += deltalambda;
  8805. deltalambdaTot += deltalambda > 0.0 ? deltalambda : -deltalambda; // abs(deltalambda)
  8806. c.addToWlambda(deltalambda);
  8807. }
  8808. // If the total error is small enough - stop iterate
  8809. if(deltalambdaTot*deltalambdaTot < tolSquared){
  8810. break;
  8811. }
  8812. }
  8813. // Add result to velocity
  8814. for(var i=0; i!==Nbodies; i++){
  8815. var b=bodies[i],
  8816. v=b.velocity,
  8817. w=b.angularVelocity;
  8818. v.vadd(b.vlambda, v);
  8819. if(w){
  8820. w.vadd(b.wlambda, w);
  8821. }
  8822. }
  8823. }
  8824. return iter;
  8825. };
  8826. },{"../math/Quaternion":28,"../math/Vec3":30,"./Solver":47}],47:[function(_dereq_,module,exports){
  8827. module.exports = Solver;
  8828. /**
  8829. * Constraint equation solver base class.
  8830. * @class Solver
  8831. * @constructor
  8832. * @author schteppe / https://github.com/schteppe
  8833. */
  8834. function Solver(){
  8835. /**
  8836. * All equations to be solved
  8837. * @property {Array} equations
  8838. */
  8839. this.equations = [];
  8840. }
  8841. /**
  8842. * Should be implemented in subclasses!
  8843. * @method solve
  8844. * @param {Number} dt
  8845. * @param {World} world
  8846. */
  8847. Solver.prototype.solve = function(dt,world){
  8848. // Should return the number of iterations done!
  8849. return 0;
  8850. };
  8851. /**
  8852. * Add an equation
  8853. * @method addEquation
  8854. * @param {Equation} eq
  8855. */
  8856. Solver.prototype.addEquation = function(eq){
  8857. if (eq.enabled) {
  8858. this.equations.push(eq);
  8859. }
  8860. };
  8861. /**
  8862. * Remove an equation
  8863. * @method removeEquation
  8864. * @param {Equation} eq
  8865. */
  8866. Solver.prototype.removeEquation = function(eq){
  8867. var eqs = this.equations;
  8868. var i = eqs.indexOf(eq);
  8869. if(i !== -1){
  8870. eqs.splice(i,1);
  8871. }
  8872. };
  8873. /**
  8874. * Add all equations
  8875. * @method removeAllEquations
  8876. */
  8877. Solver.prototype.removeAllEquations = function(){
  8878. this.equations.length = 0;
  8879. };
  8880. },{}],48:[function(_dereq_,module,exports){
  8881. module.exports = SplitSolver;
  8882. var Vec3 = _dereq_('../math/Vec3');
  8883. var Quaternion = _dereq_('../math/Quaternion');
  8884. var Solver = _dereq_('./Solver');
  8885. var Body = _dereq_('../objects/Body');
  8886. /**
  8887. * Splits the equations into islands and solves them independently. Can improve performance.
  8888. * @class SplitSolver
  8889. * @constructor
  8890. * @extends Solver
  8891. * @param {Solver} subsolver
  8892. */
  8893. function SplitSolver(subsolver){
  8894. Solver.call(this);
  8895. this.iterations = 10;
  8896. this.tolerance = 1e-7;
  8897. this.subsolver = subsolver;
  8898. this.nodes = [];
  8899. this.nodePool = [];
  8900. // Create needed nodes, reuse if possible
  8901. while(this.nodePool.length < 128){
  8902. this.nodePool.push(this.createNode());
  8903. }
  8904. }
  8905. SplitSolver.prototype = new Solver();
  8906. // Returns the number of subsystems
  8907. var SplitSolver_solve_nodes = []; // All allocated node objects
  8908. var SplitSolver_solve_nodePool = []; // All allocated node objects
  8909. var SplitSolver_solve_eqs = []; // Temp array
  8910. var SplitSolver_solve_bds = []; // Temp array
  8911. var SplitSolver_solve_dummyWorld = {bodies:[]}; // Temp object
  8912. var STATIC = Body.STATIC;
  8913. function getUnvisitedNode(nodes){
  8914. var Nnodes = nodes.length;
  8915. for(var i=0; i!==Nnodes; i++){
  8916. var node = nodes[i];
  8917. if(!node.visited && !(node.body.type & STATIC)){
  8918. return node;
  8919. }
  8920. }
  8921. return false;
  8922. }
  8923. var queue = [];
  8924. function bfs(root,visitFunc,bds,eqs){
  8925. queue.push(root);
  8926. root.visited = true;
  8927. visitFunc(root,bds,eqs);
  8928. while(queue.length) {
  8929. var node = queue.pop();
  8930. // Loop over unvisited child nodes
  8931. var child;
  8932. while((child = getUnvisitedNode(node.children))) {
  8933. child.visited = true;
  8934. visitFunc(child,bds,eqs);
  8935. queue.push(child);
  8936. }
  8937. }
  8938. }
  8939. function visitFunc(node,bds,eqs){
  8940. bds.push(node.body);
  8941. var Neqs = node.eqs.length;
  8942. for(var i=0; i!==Neqs; i++){
  8943. var eq = node.eqs[i];
  8944. if(eqs.indexOf(eq) === -1){
  8945. eqs.push(eq);
  8946. }
  8947. }
  8948. }
  8949. SplitSolver.prototype.createNode = function(){
  8950. return { body:null, children:[], eqs:[], visited:false };
  8951. };
  8952. /**
  8953. * Solve the subsystems
  8954. * @method solve
  8955. * @param {Number} dt
  8956. * @param {World} world
  8957. */
  8958. SplitSolver.prototype.solve = function(dt,world){
  8959. var nodes=SplitSolver_solve_nodes,
  8960. nodePool=this.nodePool,
  8961. bodies=world.bodies,
  8962. equations=this.equations,
  8963. Neq=equations.length,
  8964. Nbodies=bodies.length,
  8965. subsolver=this.subsolver;
  8966. // Create needed nodes, reuse if possible
  8967. while(nodePool.length < Nbodies){
  8968. nodePool.push(this.createNode());
  8969. }
  8970. nodes.length = Nbodies;
  8971. for (var i = 0; i < Nbodies; i++) {
  8972. nodes[i] = nodePool[i];
  8973. }
  8974. // Reset node values
  8975. for(var i=0; i!==Nbodies; i++){
  8976. var node = nodes[i];
  8977. node.body = bodies[i];
  8978. node.children.length = 0;
  8979. node.eqs.length = 0;
  8980. node.visited = false;
  8981. }
  8982. for(var k=0; k!==Neq; k++){
  8983. var eq=equations[k],
  8984. i=bodies.indexOf(eq.bi),
  8985. j=bodies.indexOf(eq.bj),
  8986. ni=nodes[i],
  8987. nj=nodes[j];
  8988. ni.children.push(nj);
  8989. ni.eqs.push(eq);
  8990. nj.children.push(ni);
  8991. nj.eqs.push(eq);
  8992. }
  8993. var child, n=0, eqs=SplitSolver_solve_eqs;
  8994. subsolver.tolerance = this.tolerance;
  8995. subsolver.iterations = this.iterations;
  8996. var dummyWorld = SplitSolver_solve_dummyWorld;
  8997. while((child = getUnvisitedNode(nodes))){
  8998. eqs.length = 0;
  8999. dummyWorld.bodies.length = 0;
  9000. bfs(child, visitFunc, dummyWorld.bodies, eqs);
  9001. var Neqs = eqs.length;
  9002. eqs = eqs.sort(sortById);
  9003. for(var i=0; i!==Neqs; i++){
  9004. subsolver.addEquation(eqs[i]);
  9005. }
  9006. var iter = subsolver.solve(dt,dummyWorld);
  9007. subsolver.removeAllEquations();
  9008. n++;
  9009. }
  9010. return n;
  9011. };
  9012. function sortById(a, b){
  9013. return b.id - a.id;
  9014. }
  9015. },{"../math/Quaternion":28,"../math/Vec3":30,"../objects/Body":31,"./Solver":47}],49:[function(_dereq_,module,exports){
  9016. /**
  9017. * Base class for objects that dispatches events.
  9018. * @class EventTarget
  9019. * @constructor
  9020. */
  9021. var EventTarget = function () {
  9022. };
  9023. module.exports = EventTarget;
  9024. EventTarget.prototype = {
  9025. constructor: EventTarget,
  9026. /**
  9027. * Add an event listener
  9028. * @method addEventListener
  9029. * @param {String} type
  9030. * @param {Function} listener
  9031. * @return {EventTarget} The self object, for chainability.
  9032. */
  9033. addEventListener: function ( type, listener ) {
  9034. if ( this._listeners === undefined ){ this._listeners = {}; }
  9035. var listeners = this._listeners;
  9036. if ( listeners[ type ] === undefined ) {
  9037. listeners[ type ] = [];
  9038. }
  9039. if ( listeners[ type ].indexOf( listener ) === - 1 ) {
  9040. listeners[ type ].push( listener );
  9041. }
  9042. return this;
  9043. },
  9044. /**
  9045. * Check if an event listener is added
  9046. * @method hasEventListener
  9047. * @param {String} type
  9048. * @param {Function} listener
  9049. * @return {Boolean}
  9050. */
  9051. hasEventListener: function ( type, listener ) {
  9052. if ( this._listeners === undefined ){ return false; }
  9053. var listeners = this._listeners;
  9054. if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
  9055. return true;
  9056. }
  9057. return false;
  9058. },
  9059. /**
  9060. * Remove an event listener
  9061. * @method removeEventListener
  9062. * @param {String} type
  9063. * @param {Function} listener
  9064. * @return {EventTarget} The self object, for chainability.
  9065. */
  9066. removeEventListener: function ( type, listener ) {
  9067. if ( this._listeners === undefined ){ return this; }
  9068. var listeners = this._listeners;
  9069. if ( listeners[type] === undefined ){ return this; }
  9070. var index = listeners[ type ].indexOf( listener );
  9071. if ( index !== - 1 ) {
  9072. listeners[ type ].splice( index, 1 );
  9073. }
  9074. return this;
  9075. },
  9076. /**
  9077. * Emit an event.
  9078. * @method dispatchEvent
  9079. * @param {Object} event
  9080. * @param {String} event.type
  9081. * @return {EventTarget} The self object, for chainability.
  9082. */
  9083. dispatchEvent: function ( event ) {
  9084. if ( this._listeners === undefined ){ return this; }
  9085. var listeners = this._listeners;
  9086. var listenerArray = listeners[ event.type ];
  9087. if ( listenerArray !== undefined ) {
  9088. event.target = this;
  9089. for ( var i = 0, l = listenerArray.length; i < l; i ++ ) {
  9090. listenerArray[ i ].call( this, event );
  9091. }
  9092. }
  9093. return this;
  9094. }
  9095. };
  9096. },{}],50:[function(_dereq_,module,exports){
  9097. var AABB = _dereq_('../collision/AABB');
  9098. var Vec3 = _dereq_('../math/Vec3');
  9099. module.exports = Octree;
  9100. /**
  9101. * @class OctreeNode
  9102. * @param {object} [options]
  9103. * @param {Octree} [options.root]
  9104. * @param {AABB} [options.aabb]
  9105. */
  9106. function OctreeNode(options){
  9107. options = options || {};
  9108. /**
  9109. * The root node
  9110. * @property {OctreeNode} root
  9111. */
  9112. this.root = options.root || null;
  9113. /**
  9114. * Boundary of this node
  9115. * @property {AABB} aabb
  9116. */
  9117. this.aabb = options.aabb ? options.aabb.clone() : new AABB();
  9118. /**
  9119. * Contained data at the current node level.
  9120. * @property {Array} data
  9121. */
  9122. this.data = [];
  9123. /**
  9124. * Children to this node
  9125. * @property {Array} children
  9126. */
  9127. this.children = [];
  9128. }
  9129. /**
  9130. * @class Octree
  9131. * @param {AABB} aabb The total AABB of the tree
  9132. * @param {object} [options]
  9133. * @param {number} [options.maxDepth=8]
  9134. * @extends OctreeNode
  9135. */
  9136. function Octree(aabb, options){
  9137. options = options || {};
  9138. options.root = null;
  9139. options.aabb = aabb;
  9140. OctreeNode.call(this, options);
  9141. /**
  9142. * Maximum subdivision depth
  9143. * @property {number} maxDepth
  9144. */
  9145. this.maxDepth = typeof(options.maxDepth) !== 'undefined' ? options.maxDepth : 8;
  9146. }
  9147. Octree.prototype = new OctreeNode();
  9148. OctreeNode.prototype.reset = function(aabb, options){
  9149. this.children.length = this.data.length = 0;
  9150. };
  9151. /**
  9152. * Insert data into this node
  9153. * @method insert
  9154. * @param {AABB} aabb
  9155. * @param {object} elementData
  9156. * @return {boolean} True if successful, otherwise false
  9157. */
  9158. OctreeNode.prototype.insert = function(aabb, elementData, level){
  9159. var nodeData = this.data;
  9160. level = level || 0;
  9161. // Ignore objects that do not belong in this node
  9162. if (!this.aabb.contains(aabb)){
  9163. return false; // object cannot be added
  9164. }
  9165. var children = this.children;
  9166. if(level < (this.maxDepth || this.root.maxDepth)){
  9167. // Subdivide if there are no children yet
  9168. var subdivided = false;
  9169. if (!children.length){
  9170. this.subdivide();
  9171. subdivided = true;
  9172. }
  9173. // add to whichever node will accept it
  9174. for (var i = 0; i !== 8; i++) {
  9175. if (children[i].insert(aabb, elementData, level + 1)){
  9176. return true;
  9177. }
  9178. }
  9179. if(subdivided){
  9180. // No children accepted! Might as well just remove em since they contain none
  9181. children.length = 0;
  9182. }
  9183. }
  9184. // Too deep, or children didnt want it. add it in current node
  9185. nodeData.push(elementData);
  9186. return true;
  9187. };
  9188. var halfDiagonal = new Vec3();
  9189. /**
  9190. * Create 8 equally sized children nodes and put them in the .children array.
  9191. * @method subdivide
  9192. */
  9193. OctreeNode.prototype.subdivide = function() {
  9194. var aabb = this.aabb;
  9195. var l = aabb.lowerBound;
  9196. var u = aabb.upperBound;
  9197. var children = this.children;
  9198. children.push(
  9199. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(0,0,0) }) }),
  9200. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(1,0,0) }) }),
  9201. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(1,1,0) }) }),
  9202. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(1,1,1) }) }),
  9203. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(0,1,1) }) }),
  9204. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(0,0,1) }) }),
  9205. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(1,0,1) }) }),
  9206. new OctreeNode({ aabb: new AABB({ lowerBound: new Vec3(0,1,0) }) })
  9207. );
  9208. u.vsub(l, halfDiagonal);
  9209. halfDiagonal.scale(0.5, halfDiagonal);
  9210. var root = this.root || this;
  9211. for (var i = 0; i !== 8; i++) {
  9212. var child = children[i];
  9213. // Set current node as root
  9214. child.root = root;
  9215. // Compute bounds
  9216. var lowerBound = child.aabb.lowerBound;
  9217. lowerBound.x *= halfDiagonal.x;
  9218. lowerBound.y *= halfDiagonal.y;
  9219. lowerBound.z *= halfDiagonal.z;
  9220. lowerBound.vadd(l, lowerBound);
  9221. // Upper bound is always lower bound + halfDiagonal
  9222. lowerBound.vadd(halfDiagonal, child.aabb.upperBound);
  9223. }
  9224. };
  9225. /**
  9226. * Get all data, potentially within an AABB
  9227. * @method aabbQuery
  9228. * @param {AABB} aabb
  9229. * @param {array} result
  9230. * @return {array} The "result" object
  9231. */
  9232. OctreeNode.prototype.aabbQuery = function(aabb, result) {
  9233. var nodeData = this.data;
  9234. // abort if the range does not intersect this node
  9235. // if (!this.aabb.overlaps(aabb)){
  9236. // return result;
  9237. // }
  9238. // Add objects at this level
  9239. // Array.prototype.push.apply(result, nodeData);
  9240. // Add child data
  9241. // @todo unwrap recursion into a queue / loop, that's faster in JS
  9242. var children = this.children;
  9243. // for (var i = 0, N = this.children.length; i !== N; i++) {
  9244. // children[i].aabbQuery(aabb, result);
  9245. // }
  9246. var queue = [this];
  9247. while (queue.length) {
  9248. var node = queue.pop();
  9249. if (node.aabb.overlaps(aabb)){
  9250. Array.prototype.push.apply(result, node.data);
  9251. }
  9252. Array.prototype.push.apply(queue, node.children);
  9253. }
  9254. return result;
  9255. };
  9256. var tmpAABB = new AABB();
  9257. /**
  9258. * Get all data, potentially intersected by a ray.
  9259. * @method rayQuery
  9260. * @param {Ray} ray
  9261. * @param {Transform} treeTransform
  9262. * @param {array} result
  9263. * @return {array} The "result" object
  9264. */
  9265. OctreeNode.prototype.rayQuery = function(ray, treeTransform, result) {
  9266. // Use aabb query for now.
  9267. // @todo implement real ray query which needs less lookups
  9268. ray.getAABB(tmpAABB);
  9269. tmpAABB.toLocalFrame(treeTransform, tmpAABB);
  9270. this.aabbQuery(tmpAABB, result);
  9271. return result;
  9272. };
  9273. /**
  9274. * @method removeEmptyNodes
  9275. */
  9276. OctreeNode.prototype.removeEmptyNodes = function() {
  9277. var queue = [this];
  9278. while (queue.length) {
  9279. var node = queue.pop();
  9280. for (var i = node.children.length - 1; i >= 0; i--) {
  9281. if(!node.children[i].data.length){
  9282. node.children.splice(i, 1);
  9283. }
  9284. }
  9285. Array.prototype.push.apply(queue, node.children);
  9286. }
  9287. };
  9288. },{"../collision/AABB":3,"../math/Vec3":30}],51:[function(_dereq_,module,exports){
  9289. module.exports = Pool;
  9290. /**
  9291. * For pooling objects that can be reused.
  9292. * @class Pool
  9293. * @constructor
  9294. */
  9295. function Pool(){
  9296. /**
  9297. * The pooled objects
  9298. * @property {Array} objects
  9299. */
  9300. this.objects = [];
  9301. /**
  9302. * Constructor of the objects
  9303. * @property {mixed} type
  9304. */
  9305. this.type = Object;
  9306. }
  9307. /**
  9308. * Release an object after use
  9309. * @method release
  9310. * @param {Object} obj
  9311. */
  9312. Pool.prototype.release = function(){
  9313. var Nargs = arguments.length;
  9314. for(var i=0; i!==Nargs; i++){
  9315. this.objects.push(arguments[i]);
  9316. }
  9317. };
  9318. /**
  9319. * Get an object
  9320. * @method get
  9321. * @return {mixed}
  9322. */
  9323. Pool.prototype.get = function(){
  9324. if(this.objects.length===0){
  9325. return this.constructObject();
  9326. } else {
  9327. return this.objects.pop();
  9328. }
  9329. };
  9330. /**
  9331. * Construct an object. Should be implmented in each subclass.
  9332. * @method constructObject
  9333. * @return {mixed}
  9334. */
  9335. Pool.prototype.constructObject = function(){
  9336. throw new Error("constructObject() not implemented in this Pool subclass yet!");
  9337. };
  9338. },{}],52:[function(_dereq_,module,exports){
  9339. module.exports = TupleDictionary;
  9340. /**
  9341. * @class TupleDictionary
  9342. * @constructor
  9343. */
  9344. function TupleDictionary() {
  9345. /**
  9346. * The data storage
  9347. * @property data
  9348. * @type {Object}
  9349. */
  9350. this.data = { keys:[] };
  9351. }
  9352. /**
  9353. * @method get
  9354. * @param {Number} i
  9355. * @param {Number} j
  9356. * @return {Number}
  9357. */
  9358. TupleDictionary.prototype.get = function(i, j) {
  9359. if (i > j) {
  9360. // swap
  9361. var temp = j;
  9362. j = i;
  9363. i = temp;
  9364. }
  9365. return this.data[i+'-'+j];
  9366. };
  9367. /**
  9368. * @method set
  9369. * @param {Number} i
  9370. * @param {Number} j
  9371. * @param {Number} value
  9372. */
  9373. TupleDictionary.prototype.set = function(i, j, value) {
  9374. if (i > j) {
  9375. var temp = j;
  9376. j = i;
  9377. i = temp;
  9378. }
  9379. var key = i+'-'+j;
  9380. // Check if key already exists
  9381. if(!this.get(i,j)){
  9382. this.data.keys.push(key);
  9383. }
  9384. this.data[key] = value;
  9385. };
  9386. /**
  9387. * @method reset
  9388. */
  9389. TupleDictionary.prototype.reset = function() {
  9390. var data = this.data,
  9391. keys = data.keys;
  9392. while(keys.length > 0){
  9393. var key = keys.pop();
  9394. delete data[key];
  9395. }
  9396. };
  9397. },{}],53:[function(_dereq_,module,exports){
  9398. function Utils(){}
  9399. module.exports = Utils;
  9400. /**
  9401. * Extend an options object with default values.
  9402. * @static
  9403. * @method defaults
  9404. * @param {object} options The options object. May be falsy: in this case, a new object is created and returned.
  9405. * @param {object} defaults An object containing default values.
  9406. * @return {object} The modified options object.
  9407. */
  9408. Utils.defaults = function(options, defaults){
  9409. options = options || {};
  9410. for(var key in defaults){
  9411. if(!(key in options)){
  9412. options[key] = defaults[key];
  9413. }
  9414. }
  9415. return options;
  9416. };
  9417. },{}],54:[function(_dereq_,module,exports){
  9418. module.exports = Vec3Pool;
  9419. var Vec3 = _dereq_('../math/Vec3');
  9420. var Pool = _dereq_('./Pool');
  9421. /**
  9422. * @class Vec3Pool
  9423. * @constructor
  9424. * @extends Pool
  9425. */
  9426. function Vec3Pool(){
  9427. Pool.call(this);
  9428. this.type = Vec3;
  9429. }
  9430. Vec3Pool.prototype = new Pool();
  9431. /**
  9432. * Construct a vector
  9433. * @method constructObject
  9434. * @return {Vec3}
  9435. */
  9436. Vec3Pool.prototype.constructObject = function(){
  9437. return new Vec3();
  9438. };
  9439. },{"../math/Vec3":30,"./Pool":51}],55:[function(_dereq_,module,exports){
  9440. module.exports = Narrowphase;
  9441. var AABB = _dereq_('../collision/AABB');
  9442. var Shape = _dereq_('../shapes/Shape');
  9443. var Ray = _dereq_('../collision/Ray');
  9444. var Vec3 = _dereq_('../math/Vec3');
  9445. var Transform = _dereq_('../math/Transform');
  9446. var ConvexPolyhedron = _dereq_('../shapes/ConvexPolyhedron');
  9447. var Quaternion = _dereq_('../math/Quaternion');
  9448. var Solver = _dereq_('../solver/Solver');
  9449. var Vec3Pool = _dereq_('../utils/Vec3Pool');
  9450. var ContactEquation = _dereq_('../equations/ContactEquation');
  9451. var FrictionEquation = _dereq_('../equations/FrictionEquation');
  9452. /**
  9453. * Helper class for the World. Generates ContactEquations.
  9454. * @class Narrowphase
  9455. * @constructor
  9456. * @todo Sphere-ConvexPolyhedron contacts
  9457. * @todo Contact reduction
  9458. * @todo should move methods to prototype
  9459. */
  9460. function Narrowphase(world){
  9461. /**
  9462. * Internal storage of pooled contact points.
  9463. * @property {Array} contactPointPool
  9464. */
  9465. this.contactPointPool = [];
  9466. this.frictionEquationPool = [];
  9467. this.result = [];
  9468. this.frictionResult = [];
  9469. /**
  9470. * Pooled vectors.
  9471. * @property {Vec3Pool} v3pool
  9472. */
  9473. this.v3pool = new Vec3Pool();
  9474. this.world = world;
  9475. this.currentContactMaterial = null;
  9476. /**
  9477. * @property {Boolean} enableFrictionReduction
  9478. */
  9479. this.enableFrictionReduction = false;
  9480. }
  9481. /**
  9482. * Make a contact object, by using the internal pool or creating a new one.
  9483. * @method createContactEquation
  9484. * @return {ContactEquation}
  9485. */
  9486. Narrowphase.prototype.createContactEquation = function(bi, bj, si, sj, rsi, rsj){
  9487. var c;
  9488. if(this.contactPointPool.length){
  9489. c = this.contactPointPool.pop();
  9490. c.bi = bi;
  9491. c.bj = bj;
  9492. } else {
  9493. c = new ContactEquation(bi, bj);
  9494. }
  9495. c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;
  9496. var cm = this.currentContactMaterial;
  9497. c.restitution = cm.restitution;
  9498. c.setSpookParams(
  9499. cm.contactEquationStiffness,
  9500. cm.contactEquationRelaxation,
  9501. this.world.dt
  9502. );
  9503. var matA = si.material || bi.material;
  9504. var matB = sj.material || bj.material;
  9505. if(matA && matB && matA.restitution >= 0 && matB.restitution >= 0){
  9506. c.restitution = matA.restitution * matB.restitution;
  9507. }
  9508. c.si = rsi || si;
  9509. c.sj = rsj || sj;
  9510. return c;
  9511. };
  9512. Narrowphase.prototype.createFrictionEquationsFromContact = function(contactEquation, outArray){
  9513. var bodyA = contactEquation.bi;
  9514. var bodyB = contactEquation.bj;
  9515. var shapeA = contactEquation.si;
  9516. var shapeB = contactEquation.sj;
  9517. var world = this.world;
  9518. var cm = this.currentContactMaterial;
  9519. // If friction or restitution were specified in the material, use them
  9520. var friction = cm.friction;
  9521. var matA = shapeA.material || bodyA.material;
  9522. var matB = shapeB.material || bodyB.material;
  9523. if(matA && matB && matA.friction >= 0 && matB.friction >= 0){
  9524. friction = matA.friction * matB.friction;
  9525. }
  9526. if(friction > 0){
  9527. // Create 2 tangent equations
  9528. var mug = friction * world.gravity.length();
  9529. var reducedMass = (bodyA.invMass + bodyB.invMass);
  9530. if(reducedMass > 0){
  9531. reducedMass = 1/reducedMass;
  9532. }
  9533. var pool = this.frictionEquationPool;
  9534. var c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA,bodyB,mug*reducedMass);
  9535. var c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA,bodyB,mug*reducedMass);
  9536. c1.bi = c2.bi = bodyA;
  9537. c1.bj = c2.bj = bodyB;
  9538. c1.minForce = c2.minForce = -mug*reducedMass;
  9539. c1.maxForce = c2.maxForce = mug*reducedMass;
  9540. // Copy over the relative vectors
  9541. c1.ri.copy(contactEquation.ri);
  9542. c1.rj.copy(contactEquation.rj);
  9543. c2.ri.copy(contactEquation.ri);
  9544. c2.rj.copy(contactEquation.rj);
  9545. // Construct tangents
  9546. contactEquation.ni.tangents(c1.t, c2.t);
  9547. // Set spook params
  9548. c1.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
  9549. c2.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
  9550. c1.enabled = c2.enabled = contactEquation.enabled;
  9551. outArray.push(c1, c2);
  9552. return true;
  9553. }
  9554. return false;
  9555. };
  9556. var averageNormal = new Vec3();
  9557. var averageContactPointA = new Vec3();
  9558. var averageContactPointB = new Vec3();
  9559. // Take the average N latest contact point on the plane.
  9560. Narrowphase.prototype.createFrictionFromAverage = function(numContacts){
  9561. // The last contactEquation
  9562. var c = this.result[this.result.length - 1];
  9563. // Create the result: two "average" friction equations
  9564. if (!this.createFrictionEquationsFromContact(c, this.frictionResult) || numContacts === 1) {
  9565. return;
  9566. }
  9567. var f1 = this.frictionResult[this.frictionResult.length - 2];
  9568. var f2 = this.frictionResult[this.frictionResult.length - 1];
  9569. averageNormal.setZero();
  9570. averageContactPointA.setZero();
  9571. averageContactPointB.setZero();
  9572. var bodyA = c.bi;
  9573. var bodyB = c.bj;
  9574. for(var i=0; i!==numContacts; i++){
  9575. c = this.result[this.result.length - 1 - i];
  9576. if(c.bodyA !== bodyA){
  9577. averageNormal.vadd(c.ni, averageNormal); // vec2.add(eq.t, eq.t, c.normalA);
  9578. averageContactPointA.vadd(c.ri, averageContactPointA); // vec2.add(eq.contactPointA, eq.contactPointA, c.contactPointA);
  9579. averageContactPointB.vadd(c.rj, averageContactPointB);
  9580. } else {
  9581. averageNormal.vsub(c.ni, averageNormal); // vec2.sub(eq.t, eq.t, c.normalA);
  9582. averageContactPointA.vadd(c.rj, averageContactPointA); // vec2.add(eq.contactPointA, eq.contactPointA, c.contactPointA);
  9583. averageContactPointB.vadd(c.ri, averageContactPointB);
  9584. }
  9585. }
  9586. var invNumContacts = 1 / numContacts;
  9587. averageContactPointA.scale(invNumContacts, f1.ri); // vec2.scale(eq.contactPointA, eq.contactPointA, invNumContacts);
  9588. averageContactPointB.scale(invNumContacts, f1.rj); // vec2.scale(eq.contactPointB, eq.contactPointB, invNumContacts);
  9589. f2.ri.copy(f1.ri); // Should be the same
  9590. f2.rj.copy(f1.rj);
  9591. averageNormal.normalize();
  9592. averageNormal.tangents(f1.t, f2.t);
  9593. // return eq;
  9594. };
  9595. var tmpVec1 = new Vec3();
  9596. var tmpVec2 = new Vec3();
  9597. var tmpQuat1 = new Quaternion();
  9598. var tmpQuat2 = new Quaternion();
  9599. /**
  9600. * Generate all contacts between a list of body pairs
  9601. * @method getContacts
  9602. * @param {array} p1 Array of body indices
  9603. * @param {array} p2 Array of body indices
  9604. * @param {World} world
  9605. * @param {array} result Array to store generated contacts
  9606. * @param {array} oldcontacts Optional. Array of reusable contact objects
  9607. */
  9608. Narrowphase.prototype.getContacts = function(p1, p2, world, result, oldcontacts, frictionResult, frictionPool){
  9609. // Save old contact objects
  9610. this.contactPointPool = oldcontacts;
  9611. this.frictionEquationPool = frictionPool;
  9612. this.result = result;
  9613. this.frictionResult = frictionResult;
  9614. var qi = tmpQuat1;
  9615. var qj = tmpQuat2;
  9616. var xi = tmpVec1;
  9617. var xj = tmpVec2;
  9618. for(var k=0, N=p1.length; k!==N; k++){
  9619. // Get current collision bodies
  9620. var bi = p1[k],
  9621. bj = p2[k];
  9622. // Get contact material
  9623. //miner使用两个body的材质的弹力和摩擦力
  9624. var bodyContactMaterial = false;
  9625. if(bi.material && bj.material){
  9626. bodyContactMaterial =true;//world.getContactMaterial(bi.material,bj.material) || null;
  9627. }
  9628. for (var i = 0; i < bi.shapes.length; i++) {
  9629. bi.quaternion.mult(bi.shapeOrientations[i], qi);
  9630. bi.quaternion.vmult(bi.shapeOffsets[i], xi);
  9631. xi.vadd(bi.position, xi);
  9632. var si = bi.shapes[i];
  9633. for (var j = 0; j < bj.shapes.length; j++) {
  9634. // Compute world transform of shapes
  9635. bj.quaternion.mult(bj.shapeOrientations[j], qj);
  9636. bj.quaternion.vmult(bj.shapeOffsets[j], xj);
  9637. xj.vadd(bj.position, xj);
  9638. var sj = bj.shapes[j];
  9639. if(xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius){
  9640. continue;
  9641. }
  9642. // Get collision material
  9643. var shapeContactMaterial = null;
  9644. if(si.material && sj.material){
  9645. shapeContactMaterial = world.getContactMaterial(si.material,sj.material) || null;
  9646. }
  9647. // Layaminer在这儿改掉
  9648. // this.currentContactMaterial = shapeContactMaterial || bodyContactMaterial || world.defaultContactMaterial;
  9649. if(bodyContactMaterial)
  9650. {
  9651. this.currentContactMaterial = world.defaultContactMaterial2;
  9652. this.currentContactMaterial.materials[0] = bi.material;
  9653. this.currentContactMaterial.materials[1] = bj.material;
  9654. this.currentContactMaterial.friction =bi.material.friction+ bj.material.friction;
  9655. this.currentContactMaterial.restitution = bi.material.restitution*bj.material.restitution;
  9656. }
  9657. else
  9658. this.currentContactMaterial = world.defaultContactMaterial2;
  9659. this.currentContactMaterial = world.defaultContactMaterial2;
  9660. // Get contacts
  9661. var resolver = this[si.type | sj.type];
  9662. if(resolver){
  9663. if (si.type < sj.type) {
  9664. resolver.call(this, si, sj, xi, xj, qi, qj, bi, bj, si, sj);
  9665. } else {
  9666. resolver.call(this, sj, si, xj, xi, qj, qi, bj, bi, si, sj);
  9667. }
  9668. }
  9669. }
  9670. }
  9671. }
  9672. };
  9673. var numWarnings = 0;
  9674. var maxWarnings = 10;
  9675. function warn(msg){
  9676. if(numWarnings > maxWarnings){
  9677. return;
  9678. }
  9679. numWarnings++;
  9680. console.warn(msg);
  9681. }
  9682. Narrowphase.prototype[Shape.types.BOX | Shape.types.BOX] =
  9683. Narrowphase.prototype.boxBox = function(si,sj,xi,xj,qi,qj,bi,bj){
  9684. si.convexPolyhedronRepresentation.material = si.material;
  9685. sj.convexPolyhedronRepresentation.material = sj.material;
  9686. si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
  9687. sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
  9688. this.convexConvex(si.convexPolyhedronRepresentation,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj,si,sj);
  9689. };
  9690. Narrowphase.prototype[Shape.types.BOX | Shape.types.CONVEXPOLYHEDRON] =
  9691. Narrowphase.prototype.boxConvex = function(si,sj,xi,xj,qi,qj,bi,bj){
  9692. si.convexPolyhedronRepresentation.material = si.material;
  9693. si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
  9694. this.convexConvex(si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj,si,sj);
  9695. };
  9696. Narrowphase.prototype[Shape.types.BOX | Shape.types.PARTICLE] =
  9697. Narrowphase.prototype.boxParticle = function(si,sj,xi,xj,qi,qj,bi,bj){
  9698. si.convexPolyhedronRepresentation.material = si.material;
  9699. si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
  9700. this.convexParticle(si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj,si,sj);
  9701. };
  9702. /**
  9703. * @method sphereSphere
  9704. * @param {Shape} si
  9705. * @param {Shape} sj
  9706. * @param {Vec3} xi
  9707. * @param {Vec3} xj
  9708. * @param {Quaternion} qi
  9709. * @param {Quaternion} qj
  9710. * @param {Body} bi
  9711. * @param {Body} bj
  9712. */
  9713. Narrowphase.prototype[Shape.types.SPHERE] =
  9714. Narrowphase.prototype.sphereSphere = function(si,sj,xi,xj,qi,qj,bi,bj){
  9715. // We will have only one contact in this case
  9716. var r = this.createContactEquation(bi,bj,si,sj);
  9717. // Contact normal
  9718. xj.vsub(xi, r.ni);
  9719. r.ni.normalize();
  9720. // Contact point locations
  9721. r.ri.copy(r.ni);
  9722. r.rj.copy(r.ni);
  9723. r.ri.mult(si.radius, r.ri);
  9724. r.rj.mult(-sj.radius, r.rj);
  9725. r.ri.vadd(xi, r.ri);
  9726. r.ri.vsub(bi.position, r.ri);
  9727. r.rj.vadd(xj, r.rj);
  9728. r.rj.vsub(bj.position, r.rj);
  9729. this.result.push(r);
  9730. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9731. };
  9732. /**
  9733. * @method planeTrimesh
  9734. * @param {Shape} si
  9735. * @param {Shape} sj
  9736. * @param {Vec3} xi
  9737. * @param {Vec3} xj
  9738. * @param {Quaternion} qi
  9739. * @param {Quaternion} qj
  9740. * @param {Body} bi
  9741. * @param {Body} bj
  9742. */
  9743. var planeTrimesh_normal = new Vec3();
  9744. var planeTrimesh_relpos = new Vec3();
  9745. var planeTrimesh_projected = new Vec3();
  9746. Narrowphase.prototype[Shape.types.PLANE | Shape.types.TRIMESH] =
  9747. Narrowphase.prototype.planeTrimesh = function(
  9748. planeShape,
  9749. trimeshShape,
  9750. planePos,
  9751. trimeshPos,
  9752. planeQuat,
  9753. trimeshQuat,
  9754. planeBody,
  9755. trimeshBody
  9756. ){
  9757. // Make contacts!
  9758. var v = new Vec3();
  9759. var normal = planeTrimesh_normal;
  9760. normal.set(0,0,1);
  9761. planeQuat.vmult(normal,normal); // Turn normal according to plane
  9762. for(var i=0; i<trimeshShape.vertices.length / 3; i++){
  9763. // Get world vertex from trimesh
  9764. trimeshShape.getVertex(i, v);
  9765. // Safe up
  9766. var v2 = new Vec3();
  9767. v2.copy(v);
  9768. Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
  9769. // Check plane side
  9770. var relpos = planeTrimesh_relpos;
  9771. v.vsub(planePos, relpos);
  9772. var dot = normal.dot(relpos);
  9773. if(dot <= 0.0){
  9774. var r = this.createContactEquation(planeBody,trimeshBody,planeShape,trimeshShape);
  9775. r.ni.copy(normal); // Contact normal is the plane normal
  9776. // Get vertex position projected on plane
  9777. var projected = planeTrimesh_projected;
  9778. normal.scale(relpos.dot(normal), projected);
  9779. v.vsub(projected,projected);
  9780. // ri is the projected world position minus plane position
  9781. r.ri.copy(projected);
  9782. r.ri.vsub(planeBody.position, r.ri);
  9783. r.rj.copy(v);
  9784. r.rj.vsub(trimeshBody.position, r.rj);
  9785. // Store result
  9786. this.result.push(r);
  9787. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9788. }
  9789. }
  9790. };
  9791. /**
  9792. * @method sphereTrimesh
  9793. * @param {Shape} sphereShape
  9794. * @param {Shape} trimeshShape
  9795. * @param {Vec3} spherePos
  9796. * @param {Vec3} trimeshPos
  9797. * @param {Quaternion} sphereQuat
  9798. * @param {Quaternion} trimeshQuat
  9799. * @param {Body} sphereBody
  9800. * @param {Body} trimeshBody
  9801. */
  9802. var sphereTrimesh_normal = new Vec3();
  9803. var sphereTrimesh_relpos = new Vec3();
  9804. var sphereTrimesh_projected = new Vec3();
  9805. var sphereTrimesh_v = new Vec3();
  9806. var sphereTrimesh_v2 = new Vec3();
  9807. var sphereTrimesh_edgeVertexA = new Vec3();
  9808. var sphereTrimesh_edgeVertexB = new Vec3();
  9809. var sphereTrimesh_edgeVector = new Vec3();
  9810. var sphereTrimesh_edgeVectorUnit = new Vec3();
  9811. var sphereTrimesh_localSpherePos = new Vec3();
  9812. var sphereTrimesh_tmp = new Vec3();
  9813. var sphereTrimesh_va = new Vec3();
  9814. var sphereTrimesh_vb = new Vec3();
  9815. var sphereTrimesh_vc = new Vec3();
  9816. var sphereTrimesh_localSphereAABB = new AABB();
  9817. var sphereTrimesh_triangles = [];
  9818. Narrowphase.prototype[Shape.types.SPHERE | Shape.types.TRIMESH] =
  9819. Narrowphase.prototype.sphereTrimesh = function (
  9820. sphereShape,
  9821. trimeshShape,
  9822. spherePos,
  9823. trimeshPos,
  9824. sphereQuat,
  9825. trimeshQuat,
  9826. sphereBody,
  9827. trimeshBody
  9828. ) {
  9829. var edgeVertexA = sphereTrimesh_edgeVertexA;
  9830. var edgeVertexB = sphereTrimesh_edgeVertexB;
  9831. var edgeVector = sphereTrimesh_edgeVector;
  9832. var edgeVectorUnit = sphereTrimesh_edgeVectorUnit;
  9833. var localSpherePos = sphereTrimesh_localSpherePos;
  9834. var tmp = sphereTrimesh_tmp;
  9835. var localSphereAABB = sphereTrimesh_localSphereAABB;
  9836. var v2 = sphereTrimesh_v2;
  9837. var relpos = sphereTrimesh_relpos;
  9838. var triangles = sphereTrimesh_triangles;
  9839. // Convert sphere position to local in the trimesh
  9840. Transform.pointToLocalFrame(trimeshPos, trimeshQuat, spherePos, localSpherePos);
  9841. // Get the aabb of the sphere locally in the trimesh
  9842. var sphereRadius = sphereShape.radius;
  9843. localSphereAABB.lowerBound.set(
  9844. localSpherePos.x - sphereRadius,
  9845. localSpherePos.y - sphereRadius,
  9846. localSpherePos.z - sphereRadius
  9847. );
  9848. localSphereAABB.upperBound.set(
  9849. localSpherePos.x + sphereRadius,
  9850. localSpherePos.y + sphereRadius,
  9851. localSpherePos.z + sphereRadius
  9852. );
  9853. trimeshShape.getTrianglesInAABB(localSphereAABB, triangles);
  9854. //for (var i = 0; i < trimeshShape.indices.length / 3; i++) triangles.push(i); // All
  9855. // Vertices
  9856. var v = sphereTrimesh_v;
  9857. var radiusSquared = sphereShape.radius * sphereShape.radius;
  9858. for(var i=0; i<triangles.length; i++){
  9859. for (var j = 0; j < 3; j++) {
  9860. trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], v);
  9861. // Check vertex overlap in sphere
  9862. v.vsub(localSpherePos, relpos);
  9863. if(relpos.norm2() <= radiusSquared){
  9864. // Safe up
  9865. v2.copy(v);
  9866. Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
  9867. v.vsub(spherePos, relpos);
  9868. var r = this.createContactEquation(sphereBody,trimeshBody,sphereShape,trimeshShape);
  9869. r.ni.copy(relpos);
  9870. r.ni.normalize();
  9871. // ri is the vector from sphere center to the sphere surface
  9872. r.ri.copy(r.ni);
  9873. r.ri.scale(sphereShape.radius, r.ri);
  9874. r.ri.vadd(spherePos, r.ri);
  9875. r.ri.vsub(sphereBody.position, r.ri);
  9876. r.rj.copy(v);
  9877. r.rj.vsub(trimeshBody.position, r.rj);
  9878. // Store result
  9879. this.result.push(r);
  9880. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9881. }
  9882. }
  9883. }
  9884. // Check all edges
  9885. for(var i=0; i<triangles.length; i++){
  9886. for (var j = 0; j < 3; j++) {
  9887. trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], edgeVertexA);
  9888. trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + ((j+1)%3)], edgeVertexB);
  9889. edgeVertexB.vsub(edgeVertexA, edgeVector);
  9890. // Project sphere position to the edge
  9891. localSpherePos.vsub(edgeVertexB, tmp);
  9892. var positionAlongEdgeB = tmp.dot(edgeVector);
  9893. localSpherePos.vsub(edgeVertexA, tmp);
  9894. var positionAlongEdgeA = tmp.dot(edgeVector);
  9895. if(positionAlongEdgeA > 0 && positionAlongEdgeB < 0){
  9896. // Now check the orthogonal distance from edge to sphere center
  9897. localSpherePos.vsub(edgeVertexA, tmp);
  9898. edgeVectorUnit.copy(edgeVector);
  9899. edgeVectorUnit.normalize();
  9900. positionAlongEdgeA = tmp.dot(edgeVectorUnit);
  9901. edgeVectorUnit.scale(positionAlongEdgeA, tmp);
  9902. tmp.vadd(edgeVertexA, tmp);
  9903. // tmp is now the sphere center position projected to the edge, defined locally in the trimesh frame
  9904. var dist = tmp.distanceTo(localSpherePos);
  9905. if(dist < sphereShape.radius){
  9906. var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape);
  9907. tmp.vsub(localSpherePos, r.ni);
  9908. r.ni.normalize();
  9909. r.ni.scale(sphereShape.radius, r.ri);
  9910. Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
  9911. tmp.vsub(trimeshBody.position, r.rj);
  9912. Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
  9913. Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
  9914. this.result.push(r);
  9915. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9916. }
  9917. }
  9918. }
  9919. }
  9920. // Triangle faces
  9921. var va = sphereTrimesh_va;
  9922. var vb = sphereTrimesh_vb;
  9923. var vc = sphereTrimesh_vc;
  9924. var normal = sphereTrimesh_normal;
  9925. for(var i=0, N = triangles.length; i !== N; i++){
  9926. trimeshShape.getTriangleVertices(triangles[i], va, vb, vc);
  9927. trimeshShape.getNormal(triangles[i], normal);
  9928. localSpherePos.vsub(va, tmp);
  9929. var dist = tmp.dot(normal);
  9930. normal.scale(dist, tmp);
  9931. localSpherePos.vsub(tmp, tmp);
  9932. // tmp is now the sphere position projected to the triangle plane
  9933. dist = tmp.distanceTo(localSpherePos);
  9934. if(Ray.pointInTriangle(tmp, va, vb, vc) && dist < sphereShape.radius){
  9935. var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape);
  9936. tmp.vsub(localSpherePos, r.ni);
  9937. r.ni.normalize();
  9938. r.ni.scale(sphereShape.radius, r.ri);
  9939. Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
  9940. tmp.vsub(trimeshBody.position, r.rj);
  9941. Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
  9942. Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
  9943. this.result.push(r);
  9944. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9945. }
  9946. }
  9947. triangles.length = 0;
  9948. };
  9949. var point_on_plane_to_sphere = new Vec3();
  9950. var plane_to_sphere_ortho = new Vec3();
  9951. /**
  9952. * @method spherePlane
  9953. * @param {Shape} si
  9954. * @param {Shape} sj
  9955. * @param {Vec3} xi
  9956. * @param {Vec3} xj
  9957. * @param {Quaternion} qi
  9958. * @param {Quaternion} qj
  9959. * @param {Body} bi
  9960. * @param {Body} bj
  9961. */
  9962. Narrowphase.prototype[Shape.types.SPHERE | Shape.types.PLANE] =
  9963. Narrowphase.prototype.spherePlane = function(si,sj,xi,xj,qi,qj,bi,bj){
  9964. // We will have one contact in this case
  9965. var r = this.createContactEquation(bi,bj,si,sj);
  9966. // Contact normal
  9967. r.ni.set(0,0,1);
  9968. qj.vmult(r.ni, r.ni);
  9969. r.ni.negate(r.ni); // body i is the sphere, flip normal
  9970. r.ni.normalize(); // Needed?
  9971. // Vector from sphere center to contact point
  9972. r.ni.mult(si.radius, r.ri);
  9973. // Project down sphere on plane
  9974. xi.vsub(xj, point_on_plane_to_sphere);
  9975. r.ni.mult(r.ni.dot(point_on_plane_to_sphere), plane_to_sphere_ortho);
  9976. point_on_plane_to_sphere.vsub(plane_to_sphere_ortho,r.rj); // The sphere position projected to plane
  9977. if(-point_on_plane_to_sphere.dot(r.ni) <= si.radius){
  9978. // Make it relative to the body
  9979. var ri = r.ri;
  9980. var rj = r.rj;
  9981. ri.vadd(xi, ri);
  9982. ri.vsub(bi.position, ri);
  9983. rj.vadd(xj, rj);
  9984. rj.vsub(bj.position, rj);
  9985. this.result.push(r);
  9986. this.createFrictionEquationsFromContact(r, this.frictionResult);
  9987. }
  9988. };
  9989. // See http://bulletphysics.com/Bullet/BulletFull/SphereTriangleDetector_8cpp_source.html
  9990. var pointInPolygon_edge = new Vec3();
  9991. var pointInPolygon_edge_x_normal = new Vec3();
  9992. var pointInPolygon_vtp = new Vec3();
  9993. function pointInPolygon(verts, normal, p){
  9994. var positiveResult = null;
  9995. var N = verts.length;
  9996. for(var i=0; i!==N; i++){
  9997. var v = verts[i];
  9998. // Get edge to the next vertex
  9999. var edge = pointInPolygon_edge;
  10000. verts[(i+1) % (N)].vsub(v,edge);
  10001. // Get cross product between polygon normal and the edge
  10002. var edge_x_normal = pointInPolygon_edge_x_normal;
  10003. //var edge_x_normal = new Vec3();
  10004. edge.cross(normal,edge_x_normal);
  10005. // Get vector between point and current vertex
  10006. var vertex_to_p = pointInPolygon_vtp;
  10007. p.vsub(v,vertex_to_p);
  10008. // This dot product determines which side of the edge the point is
  10009. var r = edge_x_normal.dot(vertex_to_p);
  10010. // If all such dot products have same sign, we are inside the polygon.
  10011. if(positiveResult===null || (r>0 && positiveResult===true) || (r<=0 && positiveResult===false)){
  10012. if(positiveResult===null){
  10013. positiveResult = r>0;
  10014. }
  10015. continue;
  10016. } else {
  10017. return false; // Encountered some other sign. Exit.
  10018. }
  10019. }
  10020. // If we got here, all dot products were of the same sign.
  10021. return true;
  10022. }
  10023. var box_to_sphere = new Vec3();
  10024. var sphereBox_ns = new Vec3();
  10025. var sphereBox_ns1 = new Vec3();
  10026. var sphereBox_ns2 = new Vec3();
  10027. var sphereBox_sides = [new Vec3(),new Vec3(),new Vec3(),new Vec3(),new Vec3(),new Vec3()];
  10028. var sphereBox_sphere_to_corner = new Vec3();
  10029. var sphereBox_side_ns = new Vec3();
  10030. var sphereBox_side_ns1 = new Vec3();
  10031. var sphereBox_side_ns2 = new Vec3();
  10032. /**
  10033. * @method sphereBox
  10034. * @param {Shape} si
  10035. * @param {Shape} sj
  10036. * @param {Vec3} xi
  10037. * @param {Vec3} xj
  10038. * @param {Quaternion} qi
  10039. * @param {Quaternion} qj
  10040. * @param {Body} bi
  10041. * @param {Body} bj
  10042. */
  10043. Narrowphase.prototype[Shape.types.SPHERE | Shape.types.BOX] =
  10044. Narrowphase.prototype.sphereBox = function(si,sj,xi,xj,qi,qj,bi,bj){
  10045. var v3pool = this.v3pool;
  10046. // we refer to the box as body j
  10047. var sides = sphereBox_sides;
  10048. xi.vsub(xj,box_to_sphere);
  10049. sj.getSideNormals(sides,qj);
  10050. var R = si.radius;
  10051. var penetrating_sides = [];
  10052. // Check side (plane) intersections
  10053. var found = false;
  10054. // Store the resulting side penetration info
  10055. var side_ns = sphereBox_side_ns;
  10056. var side_ns1 = sphereBox_side_ns1;
  10057. var side_ns2 = sphereBox_side_ns2;
  10058. var side_h = null;
  10059. var side_penetrations = 0;
  10060. var side_dot1 = 0;
  10061. var side_dot2 = 0;
  10062. var side_distance = null;
  10063. for(var idx=0,nsides=sides.length; idx!==nsides && found===false; idx++){
  10064. // Get the plane side normal (ns)
  10065. var ns = sphereBox_ns;
  10066. ns.copy(sides[idx]);
  10067. var h = ns.norm();
  10068. ns.normalize();
  10069. // The normal/distance dot product tells which side of the plane we are
  10070. var dot = box_to_sphere.dot(ns);
  10071. if(dot<h+R && dot>0){
  10072. // Intersects plane. Now check the other two dimensions
  10073. var ns1 = sphereBox_ns1;
  10074. var ns2 = sphereBox_ns2;
  10075. ns1.copy(sides[(idx+1)%3]);
  10076. ns2.copy(sides[(idx+2)%3]);
  10077. var h1 = ns1.norm();
  10078. var h2 = ns2.norm();
  10079. ns1.normalize();
  10080. ns2.normalize();
  10081. var dot1 = box_to_sphere.dot(ns1);
  10082. var dot2 = box_to_sphere.dot(ns2);
  10083. if(dot1<h1 && dot1>-h1 && dot2<h2 && dot2>-h2){
  10084. var dist = Math.abs(dot-h-R);
  10085. if(side_distance===null || dist < side_distance){
  10086. side_distance = dist;
  10087. side_dot1 = dot1;
  10088. side_dot2 = dot2;
  10089. side_h = h;
  10090. side_ns.copy(ns);
  10091. side_ns1.copy(ns1);
  10092. side_ns2.copy(ns2);
  10093. side_penetrations++;
  10094. }
  10095. }
  10096. }
  10097. }
  10098. if(side_penetrations){
  10099. found = true;
  10100. var r = this.createContactEquation(bi,bj,si,sj);
  10101. side_ns.mult(-R,r.ri); // Sphere r
  10102. r.ni.copy(side_ns);
  10103. r.ni.negate(r.ni); // Normal should be out of sphere
  10104. side_ns.mult(side_h,side_ns);
  10105. side_ns1.mult(side_dot1,side_ns1);
  10106. side_ns.vadd(side_ns1,side_ns);
  10107. side_ns2.mult(side_dot2,side_ns2);
  10108. side_ns.vadd(side_ns2,r.rj);
  10109. // Make relative to bodies
  10110. r.ri.vadd(xi, r.ri);
  10111. r.ri.vsub(bi.position, r.ri);
  10112. r.rj.vadd(xj, r.rj);
  10113. r.rj.vsub(bj.position, r.rj);
  10114. this.result.push(r);
  10115. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10116. }
  10117. // Check corners
  10118. var rj = v3pool.get();
  10119. var sphere_to_corner = sphereBox_sphere_to_corner;
  10120. for(var j=0; j!==2 && !found; j++){
  10121. for(var k=0; k!==2 && !found; k++){
  10122. for(var l=0; l!==2 && !found; l++){
  10123. rj.set(0,0,0);
  10124. if(j){
  10125. rj.vadd(sides[0],rj);
  10126. } else {
  10127. rj.vsub(sides[0],rj);
  10128. }
  10129. if(k){
  10130. rj.vadd(sides[1],rj);
  10131. } else {
  10132. rj.vsub(sides[1],rj);
  10133. }
  10134. if(l){
  10135. rj.vadd(sides[2],rj);
  10136. } else {
  10137. rj.vsub(sides[2],rj);
  10138. }
  10139. // World position of corner
  10140. xj.vadd(rj,sphere_to_corner);
  10141. sphere_to_corner.vsub(xi,sphere_to_corner);
  10142. if(sphere_to_corner.norm2() < R*R){
  10143. found = true;
  10144. var r = this.createContactEquation(bi,bj,si,sj);
  10145. r.ri.copy(sphere_to_corner);
  10146. r.ri.normalize();
  10147. r.ni.copy(r.ri);
  10148. r.ri.mult(R,r.ri);
  10149. r.rj.copy(rj);
  10150. // Make relative to bodies
  10151. r.ri.vadd(xi, r.ri);
  10152. r.ri.vsub(bi.position, r.ri);
  10153. r.rj.vadd(xj, r.rj);
  10154. r.rj.vsub(bj.position, r.rj);
  10155. this.result.push(r);
  10156. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10157. }
  10158. }
  10159. }
  10160. }
  10161. v3pool.release(rj);
  10162. rj = null;
  10163. // Check edges
  10164. var edgeTangent = v3pool.get();
  10165. var edgeCenter = v3pool.get();
  10166. var r = v3pool.get(); // r = edge center to sphere center
  10167. var orthogonal = v3pool.get();
  10168. var dist = v3pool.get();
  10169. var Nsides = sides.length;
  10170. for(var j=0; j!==Nsides && !found; j++){
  10171. for(var k=0; k!==Nsides && !found; k++){
  10172. if(j%3 !== k%3){
  10173. // Get edge tangent
  10174. sides[k].cross(sides[j],edgeTangent);
  10175. edgeTangent.normalize();
  10176. sides[j].vadd(sides[k], edgeCenter);
  10177. r.copy(xi);
  10178. r.vsub(edgeCenter,r);
  10179. r.vsub(xj,r);
  10180. var orthonorm = r.dot(edgeTangent); // distance from edge center to sphere center in the tangent direction
  10181. edgeTangent.mult(orthonorm,orthogonal); // Vector from edge center to sphere center in the tangent direction
  10182. // Find the third side orthogonal to this one
  10183. var l = 0;
  10184. while(l===j%3 || l===k%3){
  10185. l++;
  10186. }
  10187. // vec from edge center to sphere projected to the plane orthogonal to the edge tangent
  10188. dist.copy(xi);
  10189. dist.vsub(orthogonal,dist);
  10190. dist.vsub(edgeCenter,dist);
  10191. dist.vsub(xj,dist);
  10192. // Distances in tangent direction and distance in the plane orthogonal to it
  10193. var tdist = Math.abs(orthonorm);
  10194. var ndist = dist.norm();
  10195. if(tdist < sides[l].norm() && ndist<R){
  10196. found = true;
  10197. var res = this.createContactEquation(bi,bj,si,sj);
  10198. edgeCenter.vadd(orthogonal,res.rj); // box rj
  10199. res.rj.copy(res.rj);
  10200. dist.negate(res.ni);
  10201. res.ni.normalize();
  10202. res.ri.copy(res.rj);
  10203. res.ri.vadd(xj,res.ri);
  10204. res.ri.vsub(xi,res.ri);
  10205. res.ri.normalize();
  10206. res.ri.mult(R,res.ri);
  10207. // Make relative to bodies
  10208. res.ri.vadd(xi, res.ri);
  10209. res.ri.vsub(bi.position, res.ri);
  10210. res.rj.vadd(xj, res.rj);
  10211. res.rj.vsub(bj.position, res.rj);
  10212. this.result.push(res);
  10213. this.createFrictionEquationsFromContact(res, this.frictionResult);
  10214. }
  10215. }
  10216. }
  10217. }
  10218. v3pool.release(edgeTangent,edgeCenter,r,orthogonal,dist);
  10219. };
  10220. var convex_to_sphere = new Vec3();
  10221. var sphereConvex_edge = new Vec3();
  10222. var sphereConvex_edgeUnit = new Vec3();
  10223. var sphereConvex_sphereToCorner = new Vec3();
  10224. var sphereConvex_worldCorner = new Vec3();
  10225. var sphereConvex_worldNormal = new Vec3();
  10226. var sphereConvex_worldPoint = new Vec3();
  10227. var sphereConvex_worldSpherePointClosestToPlane = new Vec3();
  10228. var sphereConvex_penetrationVec = new Vec3();
  10229. var sphereConvex_sphereToWorldPoint = new Vec3();
  10230. /**
  10231. * @method sphereConvex
  10232. * @param {Shape} si
  10233. * @param {Shape} sj
  10234. * @param {Vec3} xi
  10235. * @param {Vec3} xj
  10236. * @param {Quaternion} qi
  10237. * @param {Quaternion} qj
  10238. * @param {Body} bi
  10239. * @param {Body} bj
  10240. */
  10241. Narrowphase.prototype[Shape.types.SPHERE | Shape.types.CONVEXPOLYHEDRON] =
  10242. Narrowphase.prototype.sphereConvex = function(si,sj,xi,xj,qi,qj,bi,bj){
  10243. var v3pool = this.v3pool;
  10244. xi.vsub(xj,convex_to_sphere);
  10245. var normals = sj.faceNormals;
  10246. var faces = sj.faces;
  10247. var verts = sj.vertices;
  10248. var R = si.radius;
  10249. var penetrating_sides = [];
  10250. // if(convex_to_sphere.norm2() > si.boundingSphereRadius + sj.boundingSphereRadius){
  10251. // return;
  10252. // }
  10253. // Check corners
  10254. for(var i=0; i!==verts.length; i++){
  10255. var v = verts[i];
  10256. // World position of corner
  10257. var worldCorner = sphereConvex_worldCorner;
  10258. qj.vmult(v,worldCorner);
  10259. xj.vadd(worldCorner,worldCorner);
  10260. var sphere_to_corner = sphereConvex_sphereToCorner;
  10261. worldCorner.vsub(xi, sphere_to_corner);
  10262. if(sphere_to_corner.norm2() < R * R){
  10263. found = true;
  10264. var r = this.createContactEquation(bi,bj,si,sj);
  10265. r.ri.copy(sphere_to_corner);
  10266. r.ri.normalize();
  10267. r.ni.copy(r.ri);
  10268. r.ri.mult(R,r.ri);
  10269. worldCorner.vsub(xj,r.rj);
  10270. // Should be relative to the body.
  10271. r.ri.vadd(xi, r.ri);
  10272. r.ri.vsub(bi.position, r.ri);
  10273. // Should be relative to the body.
  10274. r.rj.vadd(xj, r.rj);
  10275. r.rj.vsub(bj.position, r.rj);
  10276. this.result.push(r);
  10277. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10278. return;
  10279. }
  10280. }
  10281. // Check side (plane) intersections
  10282. var found = false;
  10283. for(var i=0, nfaces=faces.length; i!==nfaces && found===false; i++){
  10284. var normal = normals[i];
  10285. var face = faces[i];
  10286. // Get world-transformed normal of the face
  10287. var worldNormal = sphereConvex_worldNormal;
  10288. qj.vmult(normal,worldNormal);
  10289. // Get a world vertex from the face
  10290. var worldPoint = sphereConvex_worldPoint;
  10291. qj.vmult(verts[face[0]],worldPoint);
  10292. worldPoint.vadd(xj,worldPoint);
  10293. // Get a point on the sphere, closest to the face normal
  10294. var worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane;
  10295. worldNormal.mult(-R, worldSpherePointClosestToPlane);
  10296. xi.vadd(worldSpherePointClosestToPlane, worldSpherePointClosestToPlane);
  10297. // Vector from a face point to the closest point on the sphere
  10298. var penetrationVec = sphereConvex_penetrationVec;
  10299. worldSpherePointClosestToPlane.vsub(worldPoint,penetrationVec);
  10300. // The penetration. Negative value means overlap.
  10301. var penetration = penetrationVec.dot(worldNormal);
  10302. var worldPointToSphere = sphereConvex_sphereToWorldPoint;
  10303. xi.vsub(worldPoint, worldPointToSphere);
  10304. if(penetration < 0 && worldPointToSphere.dot(worldNormal)>0){
  10305. // Intersects plane. Now check if the sphere is inside the face polygon
  10306. var faceVerts = []; // Face vertices, in world coords
  10307. for(var j=0, Nverts=face.length; j!==Nverts; j++){
  10308. var worldVertex = v3pool.get();
  10309. qj.vmult(verts[face[j]], worldVertex);
  10310. xj.vadd(worldVertex,worldVertex);
  10311. faceVerts.push(worldVertex);
  10312. }
  10313. if(pointInPolygon(faceVerts,worldNormal,xi)){ // Is the sphere center in the face polygon?
  10314. found = true;
  10315. var r = this.createContactEquation(bi,bj,si,sj);
  10316. worldNormal.mult(-R, r.ri); // Contact offset, from sphere center to contact
  10317. worldNormal.negate(r.ni); // Normal pointing out of sphere
  10318. var penetrationVec2 = v3pool.get();
  10319. worldNormal.mult(-penetration, penetrationVec2);
  10320. var penetrationSpherePoint = v3pool.get();
  10321. worldNormal.mult(-R, penetrationSpherePoint);
  10322. //xi.vsub(xj).vadd(penetrationSpherePoint).vadd(penetrationVec2 , r.rj);
  10323. xi.vsub(xj,r.rj);
  10324. r.rj.vadd(penetrationSpherePoint,r.rj);
  10325. r.rj.vadd(penetrationVec2 , r.rj);
  10326. // Should be relative to the body.
  10327. r.rj.vadd(xj, r.rj);
  10328. r.rj.vsub(bj.position, r.rj);
  10329. // Should be relative to the body.
  10330. r.ri.vadd(xi, r.ri);
  10331. r.ri.vsub(bi.position, r.ri);
  10332. v3pool.release(penetrationVec2);
  10333. v3pool.release(penetrationSpherePoint);
  10334. this.result.push(r);
  10335. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10336. // Release world vertices
  10337. for(var j=0, Nfaceverts=faceVerts.length; j!==Nfaceverts; j++){
  10338. v3pool.release(faceVerts[j]);
  10339. }
  10340. return; // We only expect *one* face contact
  10341. } else {
  10342. // Edge?
  10343. for(var j=0; j!==face.length; j++){
  10344. // Get two world transformed vertices
  10345. var v1 = v3pool.get();
  10346. var v2 = v3pool.get();
  10347. qj.vmult(verts[face[(j+1)%face.length]], v1);
  10348. qj.vmult(verts[face[(j+2)%face.length]], v2);
  10349. xj.vadd(v1, v1);
  10350. xj.vadd(v2, v2);
  10351. // Construct edge vector
  10352. var edge = sphereConvex_edge;
  10353. v2.vsub(v1,edge);
  10354. // Construct the same vector, but normalized
  10355. var edgeUnit = sphereConvex_edgeUnit;
  10356. edge.unit(edgeUnit);
  10357. // p is xi projected onto the edge
  10358. var p = v3pool.get();
  10359. var v1_to_xi = v3pool.get();
  10360. xi.vsub(v1, v1_to_xi);
  10361. var dot = v1_to_xi.dot(edgeUnit);
  10362. edgeUnit.mult(dot, p);
  10363. p.vadd(v1, p);
  10364. // Compute a vector from p to the center of the sphere
  10365. var xi_to_p = v3pool.get();
  10366. p.vsub(xi, xi_to_p);
  10367. // Collision if the edge-sphere distance is less than the radius
  10368. // AND if p is in between v1 and v2
  10369. if(dot > 0 && dot*dot<edge.norm2() && xi_to_p.norm2() < R*R){ // Collision if the edge-sphere distance is less than the radius
  10370. // Edge contact!
  10371. var r = this.createContactEquation(bi,bj,si,sj);
  10372. p.vsub(xj,r.rj);
  10373. p.vsub(xi,r.ni);
  10374. r.ni.normalize();
  10375. r.ni.mult(R,r.ri);
  10376. // Should be relative to the body.
  10377. r.rj.vadd(xj, r.rj);
  10378. r.rj.vsub(bj.position, r.rj);
  10379. // Should be relative to the body.
  10380. r.ri.vadd(xi, r.ri);
  10381. r.ri.vsub(bi.position, r.ri);
  10382. this.result.push(r);
  10383. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10384. // Release world vertices
  10385. for(var j=0, Nfaceverts=faceVerts.length; j!==Nfaceverts; j++){
  10386. v3pool.release(faceVerts[j]);
  10387. }
  10388. v3pool.release(v1);
  10389. v3pool.release(v2);
  10390. v3pool.release(p);
  10391. v3pool.release(xi_to_p);
  10392. v3pool.release(v1_to_xi);
  10393. return;
  10394. }
  10395. v3pool.release(v1);
  10396. v3pool.release(v2);
  10397. v3pool.release(p);
  10398. v3pool.release(xi_to_p);
  10399. v3pool.release(v1_to_xi);
  10400. }
  10401. }
  10402. // Release world vertices
  10403. for(var j=0, Nfaceverts=faceVerts.length; j!==Nfaceverts; j++){
  10404. v3pool.release(faceVerts[j]);
  10405. }
  10406. }
  10407. }
  10408. };
  10409. var planeBox_normal = new Vec3();
  10410. var plane_to_corner = new Vec3();
  10411. /**
  10412. * @method planeBox
  10413. * @param {Array} result
  10414. * @param {Shape} si
  10415. * @param {Shape} sj
  10416. * @param {Vec3} xi
  10417. * @param {Vec3} xj
  10418. * @param {Quaternion} qi
  10419. * @param {Quaternion} qj
  10420. * @param {Body} bi
  10421. * @param {Body} bj
  10422. */
  10423. Narrowphase.prototype[Shape.types.PLANE | Shape.types.BOX] =
  10424. Narrowphase.prototype.planeBox = function(si,sj,xi,xj,qi,qj,bi,bj){
  10425. sj.convexPolyhedronRepresentation.material = sj.material;
  10426. sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
  10427. this.planeConvex(si,sj.convexPolyhedronRepresentation,xi,xj,qi,qj,bi,bj);
  10428. };
  10429. var planeConvex_v = new Vec3();
  10430. var planeConvex_normal = new Vec3();
  10431. var planeConvex_relpos = new Vec3();
  10432. var planeConvex_projected = new Vec3();
  10433. /**
  10434. * @method planeConvex
  10435. * @param {Shape} si
  10436. * @param {Shape} sj
  10437. * @param {Vec3} xi
  10438. * @param {Vec3} xj
  10439. * @param {Quaternion} qi
  10440. * @param {Quaternion} qj
  10441. * @param {Body} bi
  10442. * @param {Body} bj
  10443. */
  10444. Narrowphase.prototype[Shape.types.PLANE | Shape.types.CONVEXPOLYHEDRON] =
  10445. Narrowphase.prototype.planeConvex = function(
  10446. planeShape,
  10447. convexShape,
  10448. planePosition,
  10449. convexPosition,
  10450. planeQuat,
  10451. convexQuat,
  10452. planeBody,
  10453. convexBody
  10454. ){
  10455. // Simply return the points behind the plane.
  10456. var worldVertex = planeConvex_v,
  10457. worldNormal = planeConvex_normal;
  10458. worldNormal.set(0,0,1);
  10459. planeQuat.vmult(worldNormal,worldNormal); // Turn normal according to plane orientation
  10460. var numContacts = 0;
  10461. var relpos = planeConvex_relpos;
  10462. for(var i = 0; i !== convexShape.vertices.length; i++){
  10463. // Get world convex vertex
  10464. worldVertex.copy(convexShape.vertices[i]);
  10465. convexQuat.vmult(worldVertex, worldVertex);
  10466. convexPosition.vadd(worldVertex, worldVertex);
  10467. worldVertex.vsub(planePosition, relpos);
  10468. var dot = worldNormal.dot(relpos);
  10469. if(dot <= 0.0){
  10470. var r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape);
  10471. // Get vertex position projected on plane
  10472. var projected = planeConvex_projected;
  10473. worldNormal.mult(worldNormal.dot(relpos),projected);
  10474. worldVertex.vsub(projected, projected);
  10475. projected.vsub(planePosition, r.ri); // From plane to vertex projected on plane
  10476. r.ni.copy(worldNormal); // Contact normal is the plane normal out from plane
  10477. // rj is now just the vector from the convex center to the vertex
  10478. worldVertex.vsub(convexPosition, r.rj);
  10479. // Make it relative to the body
  10480. r.ri.vadd(planePosition, r.ri);
  10481. r.ri.vsub(planeBody.position, r.ri);
  10482. r.rj.vadd(convexPosition, r.rj);
  10483. r.rj.vsub(convexBody.position, r.rj);
  10484. this.result.push(r);
  10485. numContacts++;
  10486. if(!this.enableFrictionReduction){
  10487. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10488. }
  10489. }
  10490. }
  10491. if(this.enableFrictionReduction && numContacts){
  10492. this.createFrictionFromAverage(numContacts);
  10493. }
  10494. };
  10495. var convexConvex_sepAxis = new Vec3();
  10496. var convexConvex_q = new Vec3();
  10497. /**
  10498. * @method convexConvex
  10499. * @param {Shape} si
  10500. * @param {Shape} sj
  10501. * @param {Vec3} xi
  10502. * @param {Vec3} xj
  10503. * @param {Quaternion} qi
  10504. * @param {Quaternion} qj
  10505. * @param {Body} bi
  10506. * @param {Body} bj
  10507. */
  10508. Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON] =
  10509. Narrowphase.prototype.convexConvex = function(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,faceListA,faceListB){
  10510. var sepAxis = convexConvex_sepAxis;
  10511. if(xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius){
  10512. return;
  10513. }
  10514. if(si.findSeparatingAxis(sj,xi,qi,xj,qj,sepAxis,faceListA,faceListB)){
  10515. var res = [];
  10516. var q = convexConvex_q;
  10517. si.clipAgainstHull(xi,qi,sj,xj,qj,sepAxis,-100,100,res);
  10518. var numContacts = 0;
  10519. for(var j = 0; j !== res.length; j++){
  10520. var r = this.createContactEquation(bi,bj,si,sj,rsi,rsj),
  10521. ri = r.ri,
  10522. rj = r.rj;
  10523. sepAxis.negate(r.ni);
  10524. res[j].normal.negate(q);
  10525. q.mult(res[j].depth, q);
  10526. res[j].point.vadd(q, ri);
  10527. rj.copy(res[j].point);
  10528. // Contact points are in world coordinates. Transform back to relative
  10529. ri.vsub(xi,ri);
  10530. rj.vsub(xj,rj);
  10531. // Make relative to bodies
  10532. ri.vadd(xi, ri);
  10533. ri.vsub(bi.position, ri);
  10534. rj.vadd(xj, rj);
  10535. rj.vsub(bj.position, rj);
  10536. this.result.push(r);
  10537. numContacts++;
  10538. if(!this.enableFrictionReduction){
  10539. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10540. }
  10541. }
  10542. if(this.enableFrictionReduction && numContacts){
  10543. this.createFrictionFromAverage(numContacts);
  10544. }
  10545. }
  10546. };
  10547. /**
  10548. * @method convexTrimesh
  10549. * @param {Array} result
  10550. * @param {Shape} si
  10551. * @param {Shape} sj
  10552. * @param {Vec3} xi
  10553. * @param {Vec3} xj
  10554. * @param {Quaternion} qi
  10555. * @param {Quaternion} qj
  10556. * @param {Body} bi
  10557. * @param {Body} bj
  10558. */
  10559. // Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON | Shape.types.TRIMESH] =
  10560. // Narrowphase.prototype.convexTrimesh = function(si,sj,xi,xj,qi,qj,bi,bj,rsi,rsj,faceListA,faceListB){
  10561. // var sepAxis = convexConvex_sepAxis;
  10562. // if(xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius){
  10563. // return;
  10564. // }
  10565. // // Construct a temp hull for each triangle
  10566. // var hullB = new ConvexPolyhedron();
  10567. // hullB.faces = [[0,1,2]];
  10568. // var va = new Vec3();
  10569. // var vb = new Vec3();
  10570. // var vc = new Vec3();
  10571. // hullB.vertices = [
  10572. // va,
  10573. // vb,
  10574. // vc
  10575. // ];
  10576. // for (var i = 0; i < sj.indices.length / 3; i++) {
  10577. // var triangleNormal = new Vec3();
  10578. // sj.getNormal(i, triangleNormal);
  10579. // hullB.faceNormals = [triangleNormal];
  10580. // sj.getTriangleVertices(i, va, vb, vc);
  10581. // var d = si.testSepAxis(triangleNormal, hullB, xi, qi, xj, qj);
  10582. // if(!d){
  10583. // triangleNormal.scale(-1, triangleNormal);
  10584. // d = si.testSepAxis(triangleNormal, hullB, xi, qi, xj, qj);
  10585. // if(!d){
  10586. // continue;
  10587. // }
  10588. // }
  10589. // var res = [];
  10590. // var q = convexConvex_q;
  10591. // si.clipAgainstHull(xi,qi,hullB,xj,qj,triangleNormal,-100,100,res);
  10592. // for(var j = 0; j !== res.length; j++){
  10593. // var r = this.createContactEquation(bi,bj,si,sj,rsi,rsj),
  10594. // ri = r.ri,
  10595. // rj = r.rj;
  10596. // r.ni.copy(triangleNormal);
  10597. // r.ni.negate(r.ni);
  10598. // res[j].normal.negate(q);
  10599. // q.mult(res[j].depth, q);
  10600. // res[j].point.vadd(q, ri);
  10601. // rj.copy(res[j].point);
  10602. // // Contact points are in world coordinates. Transform back to relative
  10603. // ri.vsub(xi,ri);
  10604. // rj.vsub(xj,rj);
  10605. // // Make relative to bodies
  10606. // ri.vadd(xi, ri);
  10607. // ri.vsub(bi.position, ri);
  10608. // rj.vadd(xj, rj);
  10609. // rj.vsub(bj.position, rj);
  10610. // result.push(r);
  10611. // }
  10612. // }
  10613. // };
  10614. var particlePlane_normal = new Vec3();
  10615. var particlePlane_relpos = new Vec3();
  10616. var particlePlane_projected = new Vec3();
  10617. /**
  10618. * @method particlePlane
  10619. * @param {Array} result
  10620. * @param {Shape} si
  10621. * @param {Shape} sj
  10622. * @param {Vec3} xi
  10623. * @param {Vec3} xj
  10624. * @param {Quaternion} qi
  10625. * @param {Quaternion} qj
  10626. * @param {Body} bi
  10627. * @param {Body} bj
  10628. */
  10629. Narrowphase.prototype[Shape.types.PLANE | Shape.types.PARTICLE] =
  10630. Narrowphase.prototype.planeParticle = function(sj,si,xj,xi,qj,qi,bj,bi){
  10631. var normal = particlePlane_normal;
  10632. normal.set(0,0,1);
  10633. bj.quaternion.vmult(normal,normal); // Turn normal according to plane orientation
  10634. var relpos = particlePlane_relpos;
  10635. xi.vsub(bj.position,relpos);
  10636. var dot = normal.dot(relpos);
  10637. if(dot <= 0.0){
  10638. var r = this.createContactEquation(bi,bj,si,sj);
  10639. r.ni.copy(normal); // Contact normal is the plane normal
  10640. r.ni.negate(r.ni);
  10641. r.ri.set(0,0,0); // Center of particle
  10642. // Get particle position projected on plane
  10643. var projected = particlePlane_projected;
  10644. normal.mult(normal.dot(xi),projected);
  10645. xi.vsub(projected,projected);
  10646. //projected.vadd(bj.position,projected);
  10647. // rj is now the projected world position minus plane position
  10648. r.rj.copy(projected);
  10649. this.result.push(r);
  10650. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10651. }
  10652. };
  10653. var particleSphere_normal = new Vec3();
  10654. /**
  10655. * @method particleSphere
  10656. * @param {Array} result
  10657. * @param {Shape} si
  10658. * @param {Shape} sj
  10659. * @param {Vec3} xi
  10660. * @param {Vec3} xj
  10661. * @param {Quaternion} qi
  10662. * @param {Quaternion} qj
  10663. * @param {Body} bi
  10664. * @param {Body} bj
  10665. */
  10666. Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.SPHERE] =
  10667. Narrowphase.prototype.sphereParticle = function(sj,si,xj,xi,qj,qi,bj,bi){
  10668. // The normal is the unit vector from sphere center to particle center
  10669. var normal = particleSphere_normal;
  10670. normal.set(0,0,1);
  10671. xi.vsub(xj,normal);
  10672. var lengthSquared = normal.norm2();
  10673. if(lengthSquared <= sj.radius * sj.radius){
  10674. var r = this.createContactEquation(bi,bj,si,sj);
  10675. normal.normalize();
  10676. r.rj.copy(normal);
  10677. r.rj.mult(sj.radius,r.rj);
  10678. r.ni.copy(normal); // Contact normal
  10679. r.ni.negate(r.ni);
  10680. r.ri.set(0,0,0); // Center of particle
  10681. this.result.push(r);
  10682. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10683. }
  10684. };
  10685. // WIP
  10686. var cqj = new Quaternion();
  10687. var convexParticle_local = new Vec3();
  10688. var convexParticle_normal = new Vec3();
  10689. var convexParticle_penetratedFaceNormal = new Vec3();
  10690. var convexParticle_vertexToParticle = new Vec3();
  10691. var convexParticle_worldPenetrationVec = new Vec3();
  10692. /**
  10693. * @method convexParticle
  10694. * @param {Array} result
  10695. * @param {Shape} si
  10696. * @param {Shape} sj
  10697. * @param {Vec3} xi
  10698. * @param {Vec3} xj
  10699. * @param {Quaternion} qi
  10700. * @param {Quaternion} qj
  10701. * @param {Body} bi
  10702. * @param {Body} bj
  10703. */
  10704. Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.CONVEXPOLYHEDRON] =
  10705. Narrowphase.prototype.convexParticle = function(sj,si,xj,xi,qj,qi,bj,bi){
  10706. var penetratedFaceIndex = -1;
  10707. var penetratedFaceNormal = convexParticle_penetratedFaceNormal;
  10708. var worldPenetrationVec = convexParticle_worldPenetrationVec;
  10709. var minPenetration = null;
  10710. var numDetectedFaces = 0;
  10711. // Convert particle position xi to local coords in the convex
  10712. var local = convexParticle_local;
  10713. local.copy(xi);
  10714. local.vsub(xj,local); // Convert position to relative the convex origin
  10715. qj.conjugate(cqj);
  10716. cqj.vmult(local,local);
  10717. if(sj.pointIsInside(local)){
  10718. if(sj.worldVerticesNeedsUpdate){
  10719. sj.computeWorldVertices(xj,qj);
  10720. }
  10721. if(sj.worldFaceNormalsNeedsUpdate){
  10722. sj.computeWorldFaceNormals(qj);
  10723. }
  10724. // For each world polygon in the polyhedra
  10725. for(var i=0,nfaces=sj.faces.length; i!==nfaces; i++){
  10726. // Construct world face vertices
  10727. var verts = [ sj.worldVertices[ sj.faces[i][0] ] ];
  10728. var normal = sj.worldFaceNormals[i];
  10729. // Check how much the particle penetrates the polygon plane.
  10730. xi.vsub(verts[0],convexParticle_vertexToParticle);
  10731. var penetration = -normal.dot(convexParticle_vertexToParticle);
  10732. if(minPenetration===null || Math.abs(penetration)<Math.abs(minPenetration)){
  10733. minPenetration = penetration;
  10734. penetratedFaceIndex = i;
  10735. penetratedFaceNormal.copy(normal);
  10736. numDetectedFaces++;
  10737. }
  10738. }
  10739. if(penetratedFaceIndex!==-1){
  10740. // Setup contact
  10741. var r = this.createContactEquation(bi,bj,si,sj);
  10742. penetratedFaceNormal.mult(minPenetration, worldPenetrationVec);
  10743. // rj is the particle position projected to the face
  10744. worldPenetrationVec.vadd(xi,worldPenetrationVec);
  10745. worldPenetrationVec.vsub(xj,worldPenetrationVec);
  10746. r.rj.copy(worldPenetrationVec);
  10747. //var projectedToFace = xi.vsub(xj).vadd(worldPenetrationVec);
  10748. //projectedToFace.copy(r.rj);
  10749. //qj.vmult(r.rj,r.rj);
  10750. penetratedFaceNormal.negate( r.ni ); // Contact normal
  10751. r.ri.set(0,0,0); // Center of particle
  10752. var ri = r.ri,
  10753. rj = r.rj;
  10754. // Make relative to bodies
  10755. ri.vadd(xi, ri);
  10756. ri.vsub(bi.position, ri);
  10757. rj.vadd(xj, rj);
  10758. rj.vsub(bj.position, rj);
  10759. this.result.push(r);
  10760. this.createFrictionEquationsFromContact(r, this.frictionResult);
  10761. } else {
  10762. console.warn("Point found inside convex, but did not find penetrating face!");
  10763. }
  10764. }
  10765. };
  10766. Narrowphase.prototype[Shape.types.BOX | Shape.types.HEIGHTFIELD] =
  10767. Narrowphase.prototype.boxHeightfield = function (si,sj,xi,xj,qi,qj,bi,bj){
  10768. si.convexPolyhedronRepresentation.material = si.material;
  10769. si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
  10770. this.convexHeightfield(si.convexPolyhedronRepresentation,sj,xi,xj,qi,qj,bi,bj);
  10771. };
  10772. var convexHeightfield_tmp1 = new Vec3();
  10773. var convexHeightfield_tmp2 = new Vec3();
  10774. var convexHeightfield_faceList = [0];
  10775. /**
  10776. * @method convexHeightfield
  10777. */
  10778. Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON | Shape.types.HEIGHTFIELD] =
  10779. Narrowphase.prototype.convexHeightfield = function (
  10780. convexShape,
  10781. hfShape,
  10782. convexPos,
  10783. hfPos,
  10784. convexQuat,
  10785. hfQuat,
  10786. convexBody,
  10787. hfBody
  10788. ){
  10789. var data = hfShape.data,
  10790. w = hfShape.elementSize,
  10791. radius = convexShape.boundingSphereRadius,
  10792. worldPillarOffset = convexHeightfield_tmp2,
  10793. faceList = convexHeightfield_faceList;
  10794. // Get sphere position to heightfield local!
  10795. var localConvexPos = convexHeightfield_tmp1;
  10796. Transform.pointToLocalFrame(hfPos, hfQuat, convexPos, localConvexPos);
  10797. // Get the index of the data points to test against
  10798. var iMinX = Math.floor((localConvexPos.x - radius) / w) - 1,
  10799. iMaxX = Math.ceil((localConvexPos.x + radius) / w) + 1,
  10800. iMinY = Math.floor((localConvexPos.y - radius) / w) - 1,
  10801. iMaxY = Math.ceil((localConvexPos.y + radius) / w) + 1;
  10802. // Bail out if we are out of the terrain
  10803. if(iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length){
  10804. return;
  10805. }
  10806. // Clamp index to edges
  10807. if(iMinX < 0){ iMinX = 0; }
  10808. if(iMaxX < 0){ iMaxX = 0; }
  10809. if(iMinY < 0){ iMinY = 0; }
  10810. if(iMaxY < 0){ iMaxY = 0; }
  10811. if(iMinX >= data.length){ iMinX = data.length - 1; }
  10812. if(iMaxX >= data.length){ iMaxX = data.length - 1; }
  10813. if(iMaxY >= data[0].length){ iMaxY = data[0].length - 1; }
  10814. if(iMinY >= data[0].length){ iMinY = data[0].length - 1; }
  10815. var minMax = [];
  10816. hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
  10817. var min = minMax[0];
  10818. var max = minMax[1];
  10819. // Bail out if we're cant touch the bounding height box
  10820. if(localConvexPos.z - radius > max || localConvexPos.z + radius < min){
  10821. return;
  10822. }
  10823. for(var i = iMinX; i < iMaxX; i++){
  10824. for(var j = iMinY; j < iMaxY; j++){
  10825. // Lower triangle
  10826. hfShape.getConvexTrianglePillar(i, j, false);
  10827. Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
  10828. if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
  10829. this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, faceList, null);
  10830. }
  10831. // Upper triangle
  10832. hfShape.getConvexTrianglePillar(i, j, true);
  10833. Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
  10834. if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
  10835. this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, faceList, null);
  10836. }
  10837. }
  10838. }
  10839. };
  10840. var sphereHeightfield_tmp1 = new Vec3();
  10841. var sphereHeightfield_tmp2 = new Vec3();
  10842. /**
  10843. * @method sphereHeightfield
  10844. */
  10845. Narrowphase.prototype[Shape.types.SPHERE | Shape.types.HEIGHTFIELD] =
  10846. Narrowphase.prototype.sphereHeightfield = function (
  10847. sphereShape,
  10848. hfShape,
  10849. spherePos,
  10850. hfPos,
  10851. sphereQuat,
  10852. hfQuat,
  10853. sphereBody,
  10854. hfBody
  10855. ){
  10856. var data = hfShape.data,
  10857. radius = sphereShape.radius,
  10858. w = hfShape.elementSize,
  10859. worldPillarOffset = sphereHeightfield_tmp2;
  10860. // Get sphere position to heightfield local!
  10861. var localSpherePos = sphereHeightfield_tmp1;
  10862. Transform.pointToLocalFrame(hfPos, hfQuat, spherePos, localSpherePos);
  10863. // Get the index of the data points to test against
  10864. var iMinX = Math.floor((localSpherePos.x - radius) / w) - 1,
  10865. iMaxX = Math.ceil((localSpherePos.x + radius) / w) + 1,
  10866. iMinY = Math.floor((localSpherePos.y - radius) / w) - 1,
  10867. iMaxY = Math.ceil((localSpherePos.y + radius) / w) + 1;
  10868. // Bail out if we are out of the terrain
  10869. if(iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMaxY > data[0].length){
  10870. return;
  10871. }
  10872. // Clamp index to edges
  10873. if(iMinX < 0){ iMinX = 0; }
  10874. if(iMaxX < 0){ iMaxX = 0; }
  10875. if(iMinY < 0){ iMinY = 0; }
  10876. if(iMaxY < 0){ iMaxY = 0; }
  10877. if(iMinX >= data.length){ iMinX = data.length - 1; }
  10878. if(iMaxX >= data.length){ iMaxX = data.length - 1; }
  10879. if(iMaxY >= data[0].length){ iMaxY = data[0].length - 1; }
  10880. if(iMinY >= data[0].length){ iMinY = data[0].length - 1; }
  10881. var minMax = [];
  10882. hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
  10883. var min = minMax[0];
  10884. var max = minMax[1];
  10885. // Bail out if we're cant touch the bounding height box
  10886. if(localSpherePos.z - radius > max || localSpherePos.z + radius < min){
  10887. return;
  10888. }
  10889. var result = this.result;
  10890. for(var i = iMinX; i < iMaxX; i++){
  10891. for(var j = iMinY; j < iMaxY; j++){
  10892. var numContactsBefore = result.length;
  10893. // Lower triangle
  10894. hfShape.getConvexTrianglePillar(i, j, false);
  10895. Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
  10896. if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
  10897. this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody);
  10898. }
  10899. // Upper triangle
  10900. hfShape.getConvexTrianglePillar(i, j, true);
  10901. Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
  10902. if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
  10903. this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody);
  10904. }
  10905. var numContacts = result.length - numContactsBefore;
  10906. if(numContacts > 2){
  10907. return;
  10908. }
  10909. /*
  10910. // Skip all but 1
  10911. for (var k = 0; k < numContacts - 1; k++) {
  10912. result.pop();
  10913. }
  10914. */
  10915. }
  10916. }
  10917. };
  10918. },{"../collision/AABB":3,"../collision/Ray":9,"../equations/ContactEquation":19,"../equations/FrictionEquation":21,"../math/Quaternion":28,"../math/Transform":29,"../math/Vec3":30,"../shapes/ConvexPolyhedron":38,"../shapes/Shape":43,"../solver/Solver":47,"../utils/Vec3Pool":54}],56:[function(_dereq_,module,exports){
  10919. /* global performance */
  10920. module.exports = World;
  10921. var Shape = _dereq_('../shapes/Shape');
  10922. var Vec3 = _dereq_('../math/Vec3');
  10923. var Quaternion = _dereq_('../math/Quaternion');
  10924. var GSSolver = _dereq_('../solver/GSSolver');
  10925. var Vec3Pool = _dereq_('../utils/Vec3Pool');
  10926. var ContactEquation = _dereq_('../equations/ContactEquation');
  10927. var FrictionEquation = _dereq_('../equations/FrictionEquation');
  10928. var Narrowphase = _dereq_('./Narrowphase');
  10929. var EventTarget = _dereq_('../utils/EventTarget');
  10930. var ArrayCollisionMatrix = _dereq_('../collision/ArrayCollisionMatrix');
  10931. var Material = _dereq_('../material/Material');
  10932. var ContactMaterial = _dereq_('../material/ContactMaterial');
  10933. var Body = _dereq_('../objects/Body');
  10934. var TupleDictionary = _dereq_('../utils/TupleDictionary');
  10935. var RaycastResult = _dereq_('../collision/RaycastResult');
  10936. var AABB = _dereq_('../collision/AABB');
  10937. var Ray = _dereq_('../collision/Ray');
  10938. var NaiveBroadphase = _dereq_('../collision/NaiveBroadphase');
  10939. /**
  10940. * The physics world
  10941. * @class World
  10942. * @constructor
  10943. * @extends EventTarget
  10944. */
  10945. function World(){
  10946. EventTarget.apply(this);
  10947. /**
  10948. * Currently / last used timestep. Is set to -1 if not available. This value is updated before each internal step, which means that it is "fresh" inside event callbacks.
  10949. * @property {Number} dt
  10950. */
  10951. this.dt = -1;
  10952. /**
  10953. * Makes bodies go to sleep when they've been inactive
  10954. * @property allowSleep
  10955. * @type {Boolean}
  10956. */
  10957. this.allowSleep = false;
  10958. /**
  10959. * All the current contacts (instances of ContactEquation) in the world.
  10960. * @property contacts
  10961. * @type {Array}
  10962. */
  10963. this.contacts = [];
  10964. //miner所有碰撞点
  10965. this.allContacts = [];
  10966. this.frictionEquations = [];
  10967. /**
  10968. * How often to normalize quaternions. Set to 0 for every step, 1 for every second etc.. A larger value increases performance. If bodies tend to explode, set to a smaller value (zero to be sure nothing can go wrong).
  10969. * @property quatNormalizeSkip
  10970. * @type {Number}
  10971. */
  10972. this.quatNormalizeSkip = 0;
  10973. /**
  10974. * Set to true to use fast quaternion normalization. It is often enough accurate to use. If bodies tend to explode, set to false.
  10975. * @property quatNormalizeFast
  10976. * @type {Boolean}
  10977. * @see Quaternion.normalizeFast
  10978. * @see Quaternion.normalize
  10979. */
  10980. this.quatNormalizeFast = false;
  10981. /**
  10982. * The wall-clock time since simulation start
  10983. * @property time
  10984. * @type {Number}
  10985. */
  10986. this.time = 0.0;
  10987. /**
  10988. * Number of timesteps taken since start
  10989. * @property stepnumber
  10990. * @type {Number}
  10991. */
  10992. this.stepnumber = 0;
  10993. /// Default and last timestep sizes
  10994. this.default_dt = 1/60;
  10995. this.nextId = 0;
  10996. /**
  10997. * @property gravity
  10998. * @type {Vec3}
  10999. */
  11000. this.gravity = new Vec3();
  11001. /**
  11002. * @property broadphase
  11003. * @type {Broadphase}
  11004. */
  11005. this.broadphase = new NaiveBroadphase();
  11006. /**
  11007. * @property bodies
  11008. * @type {Array}
  11009. */
  11010. this.bodies = [];
  11011. /**
  11012. * miner 所有通知laya的变换Body
  11013. * @property bodies
  11014. * @type {Array}
  11015. */
  11016. this.callBackBody = [];
  11017. /**
  11018. * @property solver
  11019. * @type {Solver}
  11020. */
  11021. this.solver = new GSSolver();
  11022. /**
  11023. * @property constraints
  11024. * @type {Array}
  11025. */
  11026. this.constraints = [];
  11027. /**
  11028. * @property narrowphase
  11029. * @type {Narrowphase}
  11030. */
  11031. this.narrowphase = new Narrowphase(this);
  11032. /**
  11033. * @property {ArrayCollisionMatrix} collisionMatrix
  11034. * @type {ArrayCollisionMatrix}
  11035. */
  11036. this.collisionMatrix = new ArrayCollisionMatrix();
  11037. /**
  11038. * CollisionMatrix from the previous step.
  11039. * @property {ArrayCollisionMatrix} collisionMatrixPrevious
  11040. * @type {ArrayCollisionMatrix}
  11041. */
  11042. this.collisionMatrixPrevious = new ArrayCollisionMatrix();
  11043. /**
  11044. * All added materials
  11045. * @property materials
  11046. * @type {Array}
  11047. */
  11048. this.materials = [];
  11049. /**
  11050. * @property contactmaterials
  11051. * @type {Array}
  11052. */
  11053. this.contactmaterials = [];
  11054. /**
  11055. * Used to look up a ContactMaterial given two instances of Material.
  11056. * @property {TupleDictionary} contactMaterialTable
  11057. */
  11058. this.contactMaterialTable = new TupleDictionary();
  11059. this.defaultMaterial = new Material("default");
  11060. /**
  11061. * This contact material is used if no suitable contactmaterial is found for a contact.
  11062. * @property defaultContactMaterial
  11063. * @type {ContactMaterial}
  11064. */
  11065. this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, { friction: 0.3, restitution: 0.0 });
  11066. //miner增加一个默认的摩擦材质
  11067. this.defaultContactMaterial2 = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, { friction: 0.3, restitution: 0.0 });
  11068. /**
  11069. * @property doProfiling
  11070. * @type {Boolean}
  11071. */
  11072. this.doProfiling = false;
  11073. /**
  11074. * @property profile
  11075. * @type {Object}
  11076. */
  11077. this.profile = {
  11078. solve:0,
  11079. makeContactConstraints:0,
  11080. broadphase:0,
  11081. integrate:0,
  11082. narrowphase:0,
  11083. };
  11084. /**
  11085. * @property subsystems
  11086. * @type {Array}
  11087. */
  11088. this.subsystems = [];
  11089. this.addBodyEvent = {
  11090. type:"addBody",
  11091. body : null,
  11092. };
  11093. this.removeBodyEvent = {
  11094. type:"removeBody",
  11095. body : null,
  11096. };
  11097. }
  11098. World.prototype = new EventTarget();
  11099. // Temp stuff
  11100. var tmpAABB1 = new AABB();
  11101. var tmpArray1 = [];
  11102. var tmpRay = new Ray();
  11103. /**
  11104. * Get the contact material between materials m1 and m2
  11105. * @method getContactMaterial
  11106. * @param {Material} m1
  11107. * @param {Material} m2
  11108. * @return {ContactMaterial} The contact material if it was found.
  11109. */
  11110. World.prototype.getContactMaterial = function(m1,m2){
  11111. return this.contactMaterialTable.get(m1.id,m2.id); //this.contactmaterials[this.mats2cmat[i+j*this.materials.length]];
  11112. };
  11113. /**
  11114. * Get number of objects in the world.
  11115. * @method numObjects
  11116. * @return {Number}
  11117. * @deprecated
  11118. */
  11119. World.prototype.numObjects = function(){
  11120. return this.bodies.length;
  11121. };
  11122. /**
  11123. * Store old collision state info
  11124. * @method collisionMatrixTick
  11125. */
  11126. World.prototype.collisionMatrixTick = function(){
  11127. var temp = this.collisionMatrixPrevious;
  11128. this.collisionMatrixPrevious = this.collisionMatrix;
  11129. this.collisionMatrix = temp;
  11130. this.collisionMatrix.reset();
  11131. };
  11132. /**
  11133. * Add a rigid body to the simulation.
  11134. * @method add
  11135. * @param {Body} body
  11136. * @todo If the simulation has not yet started, why recrete and copy arrays for each body? Accumulate in dynamic arrays in this case.
  11137. * @todo Adding an array of bodies should be possible. This would save some loops too
  11138. * @deprecated Use .addBody instead
  11139. */
  11140. World.prototype.add = World.prototype.addBody = function(body){
  11141. if(this.bodies.indexOf(body) !== -1){
  11142. return;
  11143. }
  11144. body.index = this.bodies.length;
  11145. this.bodies.push(body);
  11146. body.world = this;
  11147. body.initPosition.copy(body.position);
  11148. body.initVelocity.copy(body.velocity);
  11149. body.timeLastSleepy = this.time;
  11150. if(body instanceof Body){
  11151. body.initAngularVelocity.copy(body.angularVelocity);
  11152. body.initQuaternion.copy(body.quaternion);
  11153. }
  11154. this.collisionMatrix.setNumObjects(this.bodies.length);
  11155. this.addBodyEvent.body = body;
  11156. this.dispatchEvent(this.addBodyEvent);
  11157. };
  11158. /**
  11159. * Add a constraint to the simulation.
  11160. * @method addConstraint
  11161. * @param {Constraint} c
  11162. */
  11163. World.prototype.addConstraint = function(c){
  11164. this.constraints.push(c);
  11165. };
  11166. /**
  11167. * Removes a constraint
  11168. * @method removeConstraint
  11169. * @param {Constraint} c
  11170. */
  11171. World.prototype.removeConstraint = function(c){
  11172. var idx = this.constraints.indexOf(c);
  11173. if(idx!==-1){
  11174. this.constraints.splice(idx,1);
  11175. }
  11176. };
  11177. /**
  11178. * Raycast test
  11179. * @method rayTest
  11180. * @param {Vec3} from
  11181. * @param {Vec3} to
  11182. * @param {Function|RaycastResult} result
  11183. * @deprecated Use .raycastAll, .raycastClosest or .raycastAny instead.
  11184. */
  11185. World.prototype.rayTest = function(from, to, result){
  11186. if(result instanceof RaycastResult){
  11187. // Do raycastclosest
  11188. this.raycastClosest(from, to, {
  11189. skipBackfaces: true
  11190. }, result);
  11191. } else {
  11192. // Do raycastAll
  11193. this.raycastAll(from, to, {
  11194. skipBackfaces: true
  11195. }, result);
  11196. }
  11197. };
  11198. /**
  11199. * Ray cast against all bodies. The provided callback will be executed for each hit with a RaycastResult as single argument.
  11200. * @method raycastAll
  11201. * @param {Vec3} from
  11202. * @param {Vec3} to
  11203. * @param {Object} options
  11204. * @param {number} [options.collisionFilterMask=-1]
  11205. * @param {number} [options.collisionFilterGroup=-1]
  11206. * @param {boolean} [options.skipBackfaces=false]
  11207. * @param {boolean} [options.checkCollisionResponse=true]
  11208. * @param {Function} callback
  11209. * @return {boolean} True if any body was hit.
  11210. */
  11211. World.prototype.raycastAll = function(from, to, options, callback){
  11212. options.mode = Ray.ALL;
  11213. options.from = from;
  11214. options.to = to;
  11215. options.callback = callback;
  11216. return tmpRay.intersectWorld(this, options);
  11217. };
  11218. /**
  11219. * Ray cast, and stop at the first result. Note that the order is random - but the method is fast.
  11220. * @method raycastAny
  11221. * @param {Vec3} from
  11222. * @param {Vec3} to
  11223. * @param {Object} options
  11224. * @param {number} [options.collisionFilterMask=-1]
  11225. * @param {number} [options.collisionFilterGroup=-1]
  11226. * @param {boolean} [options.skipBackfaces=false]
  11227. * @param {boolean} [options.checkCollisionResponse=true]
  11228. * @param {RaycastResult} result
  11229. * @return {boolean} True if any body was hit.
  11230. */
  11231. World.prototype.raycastAny = function(from, to, options, result){
  11232. options.mode = Ray.ANY;
  11233. options.from = from;
  11234. options.to = to;
  11235. options.result = result;
  11236. return tmpRay.intersectWorld(this, options);
  11237. };
  11238. /**
  11239. * Ray cast, and return information of the closest hit.
  11240. * @method raycastClosest
  11241. * @param {Vec3} from
  11242. * @param {Vec3} to
  11243. * @param {Object} options
  11244. * @param {number} [options.collisionFilterMask=-1]
  11245. * @param {number} [options.collisionFilterGroup=-1]
  11246. * @param {boolean} [options.skipBackfaces=false]
  11247. * @param {boolean} [options.checkCollisionResponse=true]
  11248. * @param {RaycastResult} result
  11249. * @return {boolean} True if any body was hit.
  11250. */
  11251. World.prototype.raycastClosest = function(from, to, options, result){
  11252. options.mode = Ray.CLOSEST;
  11253. options.from = from;
  11254. options.to = to;
  11255. options.result = result;
  11256. return tmpRay.intersectWorld(this, options);
  11257. };
  11258. /**
  11259. * Remove a rigid body from the simulation.
  11260. * @method remove
  11261. * @param {Body} body
  11262. * @deprecated Use .removeBody instead
  11263. */
  11264. World.prototype.remove = function(body){
  11265. body.world = null;
  11266. var n = this.bodies.length-1,
  11267. bodies = this.bodies,
  11268. idx = bodies.indexOf(body);
  11269. if(idx !== -1){
  11270. bodies.splice(idx, 1); // Todo: should use a garbage free method
  11271. // Recompute index
  11272. for(var i=0; i!==bodies.length; i++){
  11273. bodies[i].index = i;
  11274. }
  11275. this.collisionMatrix.setNumObjects(n);
  11276. this.removeBodyEvent.body = body;
  11277. this.dispatchEvent(this.removeBodyEvent);
  11278. }
  11279. };
  11280. /**
  11281. * Remove a rigid body from the simulation.
  11282. * @method removeBody
  11283. * @param {Body} body
  11284. */
  11285. World.prototype.removeBody = World.prototype.remove;
  11286. /**
  11287. * Adds a material to the World.
  11288. * @method addMaterial
  11289. * @param {Material} m
  11290. * @todo Necessary?
  11291. */
  11292. World.prototype.addMaterial = function(m){
  11293. this.materials.push(m);
  11294. };
  11295. /**
  11296. * Adds a contact material to the World
  11297. * @method addContactMaterial
  11298. * @param {ContactMaterial} cmat
  11299. */
  11300. World.prototype.addContactMaterial = function(cmat) {
  11301. // Add contact material
  11302. this.contactmaterials.push(cmat);
  11303. // Add current contact material to the material table
  11304. this.contactMaterialTable.set(cmat.materials[0].id,cmat.materials[1].id,cmat);
  11305. };
  11306. // performance.now()
  11307. if(typeof performance === 'undefined'){
  11308. performance = {};
  11309. }
  11310. if(!performance.now){
  11311. var nowOffset = Date.now();
  11312. if (performance.timing && performance.timing.navigationStart){
  11313. nowOffset = performance.timing.navigationStart;
  11314. }
  11315. performance.now = function(){
  11316. return Date.now() - nowOffset;
  11317. };
  11318. }
  11319. var step_tmp1 = new Vec3();
  11320. /**
  11321. * Step the physics world forward in time.
  11322. *
  11323. * There are two modes. The simple mode is fixed timestepping without interpolation. In this case you only use the first argument. The second case uses interpolation. In that you also provide the time since the function was last used, as well as the maximum fixed timesteps to take.
  11324. *
  11325. * @method step
  11326. * @param {Number} dt The fixed time step size to use.
  11327. * @param {Number} [timeSinceLastCalled] The time elapsed since the function was last called.
  11328. * @param {Number} [maxSubSteps=10] Maximum number of fixed steps to take per function call.
  11329. *
  11330. * @example
  11331. * // fixed timestepping without interpolation
  11332. * world.step(1/60);
  11333. *
  11334. * @see http://bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_The_World
  11335. */
  11336. World.prototype.step = function(dt, timeSinceLastCalled, maxSubSteps){
  11337. maxSubSteps = maxSubSteps || 10;
  11338. timeSinceLastCalled = timeSinceLastCalled || 0;
  11339. if(timeSinceLastCalled === 0){ // Fixed, simple stepping
  11340. this.internalStep(dt);
  11341. // Increment time
  11342. this.time += dt;
  11343. } else {
  11344. // Compute the number of fixed steps we should have taken since the last step
  11345. var internalSteps = Math.floor((this.time + timeSinceLastCalled) / dt) - Math.floor(this.time / dt);
  11346. internalSteps = Math.min(internalSteps,maxSubSteps);
  11347. // Do some fixed steps to catch up
  11348. var t0 = performance.now();
  11349. for(var i=0; i!==internalSteps; i++){
  11350. this.internalStep(dt);
  11351. if(performance.now() - t0 > dt * 1000){
  11352. // We are slower than real-time. Better bail out.
  11353. break;
  11354. }
  11355. }
  11356. // Increment internal clock
  11357. this.time += timeSinceLastCalled;
  11358. // Compute "Left over" time step
  11359. var h = this.time % dt;
  11360. var h_div_dt = h / dt;
  11361. var interpvelo = step_tmp1;
  11362. var bodies = this.bodies;
  11363. for(var j=0; j !== bodies.length; j++){
  11364. var b = bodies[j];
  11365. if(b.type !== Body.STATIC && b.sleepState !== Body.SLEEPING){
  11366. // Interpolate
  11367. b.position.vsub(b.previousPosition, interpvelo);
  11368. interpvelo.scale(h_div_dt, interpvelo);
  11369. b.position.vadd(interpvelo, b.interpolatedPosition);
  11370. // TODO: interpolate quaternion
  11371. // b.interpolatedAngle = b.angle + (b.angle - b.previousAngle) * h_div_dt;
  11372. } else {
  11373. // For static bodies, just copy. Who else will do it?
  11374. b.interpolatedPosition.copy(b.position);
  11375. b.interpolatedQuaternion.copy(b.quaternion);
  11376. }
  11377. }
  11378. }
  11379. };
  11380. /**
  11381. * Step the simulation
  11382. * @method step
  11383. * @param {Number} dt
  11384. */
  11385. var World_step_postStepEvent = {type:"postStep"}, // Reusable event objects to save memory
  11386. World_step_preStepEvent = {type:"preStep"},
  11387. World_step_collideEvent = {type:"collide", body:null, contact:null },
  11388. World_step_oldContacts = [], // Pools for unused objects
  11389. World_step_frictionEquationPool = [],
  11390. World_step_p1 = [], // Reusable arrays for collision pairs
  11391. World_step_p2 = [],
  11392. World_step_gvec = new Vec3(), // Temporary vectors and quats
  11393. World_step_vi = new Vec3(),
  11394. World_step_vj = new Vec3(),
  11395. World_step_wi = new Vec3(),
  11396. World_step_wj = new Vec3(),
  11397. World_step_t1 = new Vec3(),
  11398. World_step_t2 = new Vec3(),
  11399. World_step_rixn = new Vec3(),
  11400. World_step_rjxn = new Vec3(),
  11401. World_step_step_q = new Quaternion(),
  11402. World_step_step_w = new Quaternion(),
  11403. World_step_step_wq = new Quaternion(),
  11404. invI_tau_dt = new Vec3();
  11405. World.prototype.internalStep = function(dt){
  11406. this.dt = dt;
  11407. var world = this,
  11408. that = this,
  11409. contacts = this.contacts,
  11410. allContacts = this.allContacts,
  11411. p1 = World_step_p1,
  11412. p2 = World_step_p2,
  11413. N = this.numObjects(),
  11414. bodies = this.bodies,
  11415. solver = this.solver,
  11416. gravity = this.gravity,
  11417. doProfiling = this.doProfiling,
  11418. profile = this.profile,
  11419. DYNAMIC = Body.DYNAMIC,
  11420. profilingStart,
  11421. constraints = this.constraints,
  11422. frictionEquationPool = World_step_frictionEquationPool,
  11423. gnorm = gravity.norm(),
  11424. gx = gravity.x,
  11425. gy = gravity.y,
  11426. gz = gravity.z,
  11427. i=0;
  11428. if(doProfiling){
  11429. profilingStart = performance.now();
  11430. }
  11431. // Add gravity to all objects
  11432. for(i=0; i!==N; i++){
  11433. var bi = bodies[i];
  11434. if(bi.type & DYNAMIC){ // Only for dynamic bodies
  11435. var f = bi.force, m = bi.mass;
  11436. f.x += m*gx;
  11437. f.y += m*gy;
  11438. f.z += m*gz;
  11439. }
  11440. }
  11441. // Update subsystems
  11442. for(var i=0, Nsubsystems=this.subsystems.length; i!==Nsubsystems; i++){
  11443. this.subsystems[i].update();
  11444. }
  11445. // Collision detection
  11446. if(doProfiling){ profilingStart = performance.now(); }
  11447. p1.length = 0; // Clean up pair arrays from last step
  11448. p2.length = 0;
  11449. this.broadphase.collisionPairs(this,p1,p2);
  11450. if(doProfiling){ profile.broadphase = performance.now() - profilingStart; }
  11451. // Remove constrained pairs with collideConnected == false
  11452. var Nconstraints = constraints.length;
  11453. for(i=0; i!==Nconstraints; i++){
  11454. var c = constraints[i];
  11455. if(!c.collideConnected){
  11456. for(var j = p1.length-1; j>=0; j-=1){
  11457. if( (c.bodyA === p1[j] && c.bodyB === p2[j]) ||
  11458. (c.bodyB === p1[j] && c.bodyA === p2[j])){
  11459. p1.splice(j, 1);
  11460. p2.splice(j, 1);
  11461. }
  11462. }
  11463. }
  11464. }
  11465. this.collisionMatrixTick();
  11466. // Generate contacts
  11467. if(doProfiling){ profilingStart = performance.now(); }
  11468. var oldcontacts = World_step_oldContacts;
  11469. //miner
  11470. var NoldContacts = allContacts.length;
  11471. for(i=0; i!==NoldContacts; i++){
  11472. //miner
  11473. oldcontacts.push(allContacts[i]);
  11474. }
  11475. contacts.length = 0;
  11476. //miner
  11477. allContacts.length = 0;
  11478. // Transfer FrictionEquation from current list to the pool for reuse
  11479. var NoldFrictionEquations = this.frictionEquations.length;
  11480. for(i=0; i!==NoldFrictionEquations; i++){
  11481. frictionEquationPool.push(this.frictionEquations[i]);
  11482. }
  11483. this.frictionEquations.length = 0;
  11484. this.narrowphase.getContacts(
  11485. p1,
  11486. p2,
  11487. this,
  11488. allContacts,//miner
  11489. oldcontacts, // To be reused
  11490. this.frictionEquations,
  11491. frictionEquationPool
  11492. );
  11493. //排除istrigger的碰撞物体
  11494. var ncontactss = allContacts.length;
  11495. for(var ii = 0;ii != ncontactss;ii++)
  11496. {
  11497. var tempContact = allContacts[ii];
  11498. if(!(tempContact.bi.isTrigger||tempContact.bj.isTrigger))
  11499. {
  11500. contacts.push(tempContact);
  11501. }
  11502. }
  11503. if(doProfiling){
  11504. profile.narrowphase = performance.now() - profilingStart;
  11505. }
  11506. // Loop over all collisions
  11507. if(doProfiling){
  11508. profilingStart = performance.now();
  11509. }
  11510. // Add all friction eqs
  11511. for (var i = 0; i < this.frictionEquations.length; i++) {
  11512. solver.addEquation(this.frictionEquations[i]);
  11513. }
  11514. var ncontacts = contacts.length;
  11515. for(var k=0; k!==ncontacts; k++){
  11516. // Current contact
  11517. var c = contacts[k];
  11518. // Get current collision indeces
  11519. var bi = c.bi,
  11520. bj = c.bj,
  11521. si = c.si,
  11522. sj = c.sj;
  11523. // Get collision properties
  11524. var cm;
  11525. if(bi.material && bj.material){
  11526. cm = this.getContactMaterial(bi.material,bj.material) || this.defaultContactMaterial;
  11527. } else {
  11528. cm = this.defaultContactMaterial;
  11529. }
  11530. // c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;
  11531. var mu = cm.friction;
  11532. // c.restitution = cm.restitution;
  11533. // If friction or restitution were specified in the material, use them
  11534. if(bi.material && bj.material){
  11535. if(bi.material.friction >= 0 && bj.material.friction >= 0){
  11536. mu = bi.material.friction * bj.material.friction;
  11537. }
  11538. if(bi.material.restitution >= 0 && bj.material.restitution >= 0){
  11539. c.restitution = bi.material.restitution * bj.material.restitution;
  11540. }
  11541. }
  11542. // c.setSpookParams(
  11543. // cm.contactEquationStiffness,
  11544. // cm.contactEquationRelaxation,
  11545. // dt
  11546. // );
  11547. solver.addEquation(c);
  11548. // // Add friction constraint equation
  11549. // if(mu > 0){
  11550. // // Create 2 tangent equations
  11551. // var mug = mu * gnorm;
  11552. // var reducedMass = (bi.invMass + bj.invMass);
  11553. // if(reducedMass > 0){
  11554. // reducedMass = 1/reducedMass;
  11555. // }
  11556. // var pool = frictionEquationPool;
  11557. // var c1 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass);
  11558. // var c2 = pool.length ? pool.pop() : new FrictionEquation(bi,bj,mug*reducedMass);
  11559. // this.frictionEquations.push(c1, c2);
  11560. // c1.bi = c2.bi = bi;
  11561. // c1.bj = c2.bj = bj;
  11562. // c1.minForce = c2.minForce = -mug*reducedMass;
  11563. // c1.maxForce = c2.maxForce = mug*reducedMass;
  11564. // // Copy over the relative vectors
  11565. // c1.ri.copy(c.ri);
  11566. // c1.rj.copy(c.rj);
  11567. // c2.ri.copy(c.ri);
  11568. // c2.rj.copy(c.rj);
  11569. // // Construct tangents
  11570. // c.ni.tangents(c1.t, c2.t);
  11571. // // Set spook params
  11572. // c1.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, dt);
  11573. // c2.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, dt);
  11574. // c1.enabled = c2.enabled = c.enabled;
  11575. // // Add equations to solver
  11576. // solver.addEquation(c1);
  11577. // solver.addEquation(c2);
  11578. // }
  11579. if( bi.allowSleep &&
  11580. bi.type === Body.DYNAMIC &&
  11581. bi.sleepState === Body.SLEEPING &&
  11582. bj.sleepState === Body.AWAKE &&
  11583. bj.type !== Body.STATIC
  11584. ){
  11585. var speedSquaredB = bj.velocity.norm2() + bj.angularVelocity.norm2();
  11586. var speedLimitSquaredB = Math.pow(bj.sleepSpeedLimit,2);
  11587. if(speedSquaredB >= speedLimitSquaredB*2){
  11588. bi._wakeUpAfterNarrowphase = true;
  11589. }
  11590. }
  11591. if( bj.allowSleep &&
  11592. bj.type === Body.DYNAMIC &&
  11593. bj.sleepState === Body.SLEEPING &&
  11594. bi.sleepState === Body.AWAKE &&
  11595. bi.type !== Body.STATIC
  11596. ){
  11597. var speedSquaredA = bi.velocity.norm2() + bi.angularVelocity.norm2();
  11598. var speedLimitSquaredA = Math.pow(bi.sleepSpeedLimit,2);
  11599. if(speedSquaredA >= speedLimitSquaredA*2){
  11600. bj._wakeUpAfterNarrowphase = true;
  11601. }
  11602. }
  11603. // Now we know that i and j are in contact. Set collision matrix state
  11604. this.collisionMatrix.set(bi, bj, true);
  11605. if (!this.collisionMatrixPrevious.get(bi, bj)) {
  11606. // First contact!
  11607. // We reuse the collideEvent object, otherwise we will end up creating new objects for each new contact, even if there's no event listener attached.
  11608. World_step_collideEvent.body = bj;
  11609. World_step_collideEvent.contact = c;
  11610. bi.dispatchEvent(World_step_collideEvent);
  11611. World_step_collideEvent.body = bi;
  11612. bj.dispatchEvent(World_step_collideEvent);
  11613. }
  11614. }
  11615. if(doProfiling){
  11616. profile.makeContactConstraints = performance.now() - profilingStart;
  11617. profilingStart = performance.now();
  11618. }
  11619. // Wake up bodies
  11620. for(i=0; i!==N; i++){
  11621. var bi = bodies[i];
  11622. if(bi._wakeUpAfterNarrowphase){
  11623. bi.wakeUp();
  11624. bi._wakeUpAfterNarrowphase = false;
  11625. }
  11626. }
  11627. // Add user-added constraints
  11628. var Nconstraints = constraints.length;
  11629. for(i=0; i!==Nconstraints; i++){
  11630. var c = constraints[i];
  11631. c.update();
  11632. for(var j=0, Neq=c.equations.length; j!==Neq; j++){
  11633. var eq = c.equations[j];
  11634. solver.addEquation(eq);
  11635. }
  11636. }
  11637. // Solve the constrained system
  11638. solver.solve(dt,this);
  11639. if(doProfiling){
  11640. profile.solve = performance.now() - profilingStart;
  11641. }
  11642. // Remove all contacts from solver
  11643. solver.removeAllEquations();
  11644. // Apply damping, see http://code.google.com/p/bullet/issues/detail?id=74 for details
  11645. var pow = Math.pow;
  11646. for(i=0; i!==N; i++){
  11647. var bi = bodies[i];
  11648. if(bi.type & DYNAMIC){ // Only for dynamic bodies
  11649. var ld = pow(1.0 - bi.linearDamping,dt);
  11650. var v = bi.velocity;
  11651. v.mult(ld,v);
  11652. var av = bi.angularVelocity;
  11653. if(av){
  11654. var ad = pow(1.0 - bi.angularDamping,dt);
  11655. av.mult(ad,av);
  11656. }
  11657. }
  11658. }
  11659. this.dispatchEvent(World_step_preStepEvent);
  11660. // Invoke pre-step callbacks
  11661. for(i=0; i!==N; i++){
  11662. var bi = bodies[i];
  11663. if(bi.preStep){
  11664. bi.preStep.call(bi);
  11665. }
  11666. }
  11667. // Leap frog
  11668. // vnew = v + h*f/m
  11669. // xnew = x + h*vnew
  11670. if(doProfiling){
  11671. profilingStart = performance.now();
  11672. }
  11673. var q = World_step_step_q;
  11674. var w = World_step_step_w;
  11675. var wq = World_step_step_wq;
  11676. var stepnumber = this.stepnumber;
  11677. var DYNAMIC_OR_KINEMATIC = Body.DYNAMIC | Body.KINEMATIC;
  11678. var quatNormalize = stepnumber % (this.quatNormalizeSkip+1) === 0;
  11679. var quatNormalizeFast = this.quatNormalizeFast;
  11680. var half_dt = dt * 0.5;
  11681. var PLANE = Shape.types.PLANE,
  11682. CONVEX = Shape.types.CONVEXPOLYHEDRON;
  11683. //miner 清楚队列
  11684. this.callBackBody.length = 0;
  11685. for(i=0; i!==N; i++){
  11686. var b = bodies[i],
  11687. force = b.force,
  11688. tau = b.torque;
  11689. if((b.type & DYNAMIC_OR_KINEMATIC) && b.sleepState !== Body.SLEEPING){ // Only for dynamic
  11690. var velo = b.velocity,
  11691. angularVelo = b.angularVelocity,
  11692. pos = b.position,
  11693. quat = b.quaternion,
  11694. invMass = b.invMass,
  11695. invInertia = b.invInertiaWorld;
  11696. //miner 组织所有的变动大的物体
  11697. //miner end
  11698. velo.x += force.x * invMass * dt;
  11699. velo.y += force.y * invMass * dt;
  11700. velo.z += force.z * invMass * dt;
  11701. if(b.angularVelocity){
  11702. invInertia.vmult(tau,invI_tau_dt);
  11703. invI_tau_dt.mult(dt,invI_tau_dt);
  11704. invI_tau_dt.vadd(angularVelo,angularVelo);
  11705. }
  11706. // Use new velocity - leap frog
  11707. pos.x += velo.x * dt;
  11708. pos.y += velo.y * dt;
  11709. pos.z += velo.z * dt;
  11710. if(b.angularVelocity){
  11711. w.set(angularVelo.x, angularVelo.y, angularVelo.z, 0);
  11712. w.mult(quat,wq);
  11713. quat.x += half_dt * wq.x;
  11714. quat.y += half_dt * wq.y;
  11715. quat.z += half_dt * wq.z;
  11716. quat.w += half_dt * wq.w;
  11717. if(quatNormalize){
  11718. if(quatNormalizeFast){
  11719. quat.normalizeFast();
  11720. } else {
  11721. quat.normalize();
  11722. }
  11723. }
  11724. }
  11725. //if(velo.length()>0.0001||(wq.x!=0||wq.y!=0||wq.z!=0||wq.w!=0))
  11726. this.callBackBody.push(b);
  11727. if(b.aabb){
  11728. b.aabbNeedsUpdate = true;
  11729. }
  11730. // Update world inertia
  11731. if(b.updateInertiaWorld){
  11732. b.updateInertiaWorld();
  11733. }
  11734. }
  11735. }
  11736. this.clearForces();
  11737. this.broadphase.dirty = true;
  11738. if(doProfiling){
  11739. profile.integrate = performance.now() - profilingStart;
  11740. }
  11741. // Update world time
  11742. this.time += dt;
  11743. this.stepnumber += 1;
  11744. this.dispatchEvent(World_step_postStepEvent);
  11745. // Invoke post-step callbacks
  11746. for(i=0; i!==N; i++){
  11747. var bi = bodies[i];
  11748. var postStep = bi.postStep;
  11749. if(postStep){
  11750. postStep.call(bi);
  11751. }
  11752. }
  11753. // Sleeping update
  11754. if(this.allowSleep){
  11755. for(i=0; i!==N; i++){
  11756. bodies[i].sleepTick(this.time);
  11757. }
  11758. }
  11759. };
  11760. /**
  11761. * Sets all body forces in the world to zero.
  11762. * @method clearForces
  11763. */
  11764. World.prototype.clearForces = function(){
  11765. var bodies = this.bodies;
  11766. var N = bodies.length;
  11767. for(var i=0; i !== N; i++){
  11768. var b = bodies[i],
  11769. force = b.force,
  11770. tau = b.torque;
  11771. b.force.set(0,0,0);
  11772. b.torque.set(0,0,0);
  11773. }
  11774. };
  11775. },{"../collision/AABB":3,"../collision/ArrayCollisionMatrix":4,"../collision/NaiveBroadphase":7,"../collision/Ray":9,"../collision/RaycastResult":10,"../equations/ContactEquation":19,"../equations/FrictionEquation":21,"../material/ContactMaterial":24,"../material/Material":25,"../math/Quaternion":28,"../math/Vec3":30,"../objects/Body":31,"../shapes/Shape":43,"../solver/GSSolver":46,"../utils/EventTarget":49,"../utils/TupleDictionary":52,"../utils/Vec3Pool":54,"./Narrowphase":55}]},{},[2])
  11776. (2)
  11777. });