1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512 |
- /**
- * from OimoPhysics DEV 1.1.0a AS3
- * @author Saharan / http://el-ement.com/
- *
- * to Oimo.js 2015 JAVASCRIPT
- * @author LoTh / http://lo-th.github.io/labs/
- */
- var OIMO = {
- REVISION: "1.2",
- // Global identification of next shape.
- // This will be incremented every time a shape is created.
- nextID: 0,
- proxyID: 0,
- // BroadPhase
- BR_NULL: 0,
- BR_BRUTE_FORCE: 1,
- BR_SWEEP_AND_PRUNE: 2,
- BR_BOUNDING_VOLUME_TREE: 3,
- // body type
- BODY_NULL: 0,
- BODY_DYNAMIC: 1,
- BODY_STATIC: 2,
- // shape type
- SHAPE_NULL: 0,
- SHAPE_SPHERE: 1,
- SHAPE_BOX: 2,
- SHAPE_CYLINDER: 3,
- SHAPE_TETRA: 4,
- // joint type
- JOINT_NULL: 0,
- JOINT_DISTANCE: 1,
- JOINT_BALL_AND_SOCKET: 2,
- JOINT_HINGE: 3,
- JOINT_WHEEL: 4,
- JOINT_SLIDER: 5,
- JOINT_PRISMATIC: 6,
- // this world scale defaut is 0.1 to 10 meters max for dynamique body
- // scale all by 100 so object is between 10 to 10000 three unit.
- WORLD_SCALE: 100,
- INV_SCALE: 0.01,
- // AABB aproximation
- AABB_PROX: 0.005,
- // Math function
- sqrt: Math.sqrt,
- abs: Math.abs,
- floor: Math.floor,
- cos: Math.cos,
- sin: Math.sin,
- acos: Math.acos,
- asin: Math.asin,
- atan2: Math.atan2,
- round: Math.round,
- pow: Math.pow,
- max: Math.max,
- min: Math.min,
- random: Math.random,
- lerp: function (a, b, percent) { return a + (b - a) * percent; },
- rand: function (a, b) { return OIMO.lerp(a, b, OIMO.random()); },
- randInt: function (a, b, n) { return OIMO.lerp(a, b, OIMO.random()).toFixed(n || 0) * 1; },
- int: function (x) { return ~~x; },
- fix: function (x, n) { return x.toFixed(n || 3, 10); },
- clamp: function (value, min, max) { return OIMO.max(min, OIMO.min(max, value)); },
- degtorad: 0.0174532925199432957,
- radtodeg: 57.295779513082320876,
- PI: 3.141592653589793,
- TwoPI: 6.283185307179586,
- PI90: 1.570796326794896,
- PI270: 4.712388980384689,
- CustomError: null,
- Error: function (Class, Msg) {
- if (OIMO.CustomError == null) console.error(Class, Msg);
- else OIMO.CustomError.innerHTML += Class + " - " + Msg + '<br>';
- }
- };
- var OIMO_ARRAY_TYPE;
- if (!OIMO_ARRAY_TYPE) { OIMO_ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array; }
- try {
- (function (w) {
- var perfNow;
- var perfNowNames = ['now', 'webkitNow', 'msNow', 'mozNow'];
- if (!!w['performance']) for (var i = 0; i < perfNowNames.length; ++i) {
- var n = perfNowNames[i];
- if (!!w['performance'][n]) {
- perfNow = function () { return w['performance'][n]() };
- break;
- }
- }
- if (!perfNow) perfNow = Date.now;
- //w.perfNow = perfNow;
- OIMO.now = perfNow;
- })(window);
- } catch (e) { OIMO.now = function () { return 0; }; }
- /**
- * The class of physical computing world.
- * You must be added to the world physical all computing objects
- * @author saharan
- * @author lo-th
- */
- OIMO.World = function (TimeStep, BroadPhaseType, Iterations, NoStat) {
- // The time between each step
- this.timeStep = TimeStep || 0.01666; // 1/60;
- // The number of iterations for constraint solvers.
- this.numIterations = Iterations || 8;
- // It is a wide-area collision judgment that is used in order to reduce as much as possible a detailed collision judgment.
- switch (BroadPhaseType || 2) {
- case 1: this.broadPhase = new OIMO.BruteForceBroadPhase(); break;
- case 2: default: this.broadPhase = new OIMO.SAPBroadPhase(); break;
- case 3: this.broadPhase = new OIMO.DBVTBroadPhase(); break;
- }
- // This is the detailed information of the performance.
- this.performance = null;
- this.isNoStat = NoStat || false;
- if (!this.isNoStat) this.performance = new OIMO.Performance(this);
- // Whether the constraints randomizer is enabled or not.
- this.enableRandomizer = true;
- // The rigid body list
- this.rigidBodies = null;
- // number of rigid body
- this.numRigidBodies = 0;
- // The contact list
- this.contacts = null;
- this.unusedContacts = null;
- // The number of contact
- this.numContacts = 0;
- // The number of contact points
- this.numContactPoints = 0;
- // The joint list
- this.joints = null;
- // The number of joints.
- this.numJoints = 0;
- // The number of simulation islands.
- this.numIslands = 0;
- // The gravity in the world.
- this.gravity = new OIMO.Vec3(0, -9.80665, 0);
- var numShapeTypes = 5;//4;//3;
- this.detectors = [];
- this.detectors.length = numShapeTypes;
- var i = numShapeTypes;
- while (i--) {
- this.detectors[i] = [];
- this.detectors[i].length = numShapeTypes;
- }
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_SPHERE] = new OIMO.SphereSphereCollisionDetector();
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_BOX] = new OIMO.SphereBoxCollisionDetector(false);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_SPHERE] = new OIMO.SphereBoxCollisionDetector(true);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_BOX] = new OIMO.BoxBoxCollisionDetector();
- // CYLINDER add
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_CYLINDER] = new OIMO.CylinderCylinderCollisionDetector();
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_BOX] = new OIMO.BoxCylinderCollisionDetector(true);
- this.detectors[OIMO.SHAPE_BOX][OIMO.SHAPE_CYLINDER] = new OIMO.BoxCylinderCollisionDetector(false);
- this.detectors[OIMO.SHAPE_CYLINDER][OIMO.SHAPE_SPHERE] = new OIMO.SphereCylinderCollisionDetector(true);
- this.detectors[OIMO.SHAPE_SPHERE][OIMO.SHAPE_CYLINDER] = new OIMO.SphereCylinderCollisionDetector(false);
- // TETRA add
- this.detectors[OIMO.SHAPE_TETRA][OIMO.SHAPE_TETRA] = new OIMO.TetraTetraCollisionDetector();
- this.randX = 65535;
- this.randA = 98765;
- this.randB = 123456789;
- //this.maxIslandRigidBodies = 64;
- this.islandRigidBodies = [];
- //this.islandRigidBodies.length = this.maxIslandRigidBodies;
- this.islandStack = [];
- //this.islandStack.length = this.maxIslandRigidBodies;
- //this.maxIslandConstraints = 128;
- this.islandConstraints = [];
- //this.islandConstraints.length = this.maxIslandConstraints;
- };
- OIMO.World.prototype = {
- constructor: OIMO.World,
- /**
- * Reset the randomizer and remove all rigid bodies, shapes, joints and any object from the world.
- */
- clear: function () {
- this.randX = 65535;
- while (this.joints !== null) {
- this.removeJoint(this.joints);
- }
- while (this.contacts !== null) {
- this.removeContact(this.contacts);
- }
- while (this.rigidBodies !== null) {
- this.removeRigidBody(this.rigidBodies);
- }
- OIMO.nextID = 0;
- OIMO.proxyID = 0;
- },
- /**
- * I'll add a rigid body to the world.
- * Rigid body that has been added will be the operands of each step.
- * @param rigidBody Rigid body that you want to add
- */
- addRigidBody: function (rigidBody) {
- if (rigidBody.parent) {
- OIMO.Error("World", "It is not possible to be added to more than one world one of the rigid body");
- }
- rigidBody.parent = this;
- rigidBody.awake();
- for (var shape = rigidBody.shapes; shape !== null; shape = shape.next) {
- this.addShape(shape);
- }
- if (this.rigidBodies !== null) (this.rigidBodies.prev = rigidBody).next = this.rigidBodies;
- this.rigidBodies = rigidBody;
- this.numRigidBodies++;
- },
- /**
- * I will remove the rigid body from the world.
- * Rigid body that has been deleted is excluded from the calculation on a step-by-step basis.
- * @param rigidBody Rigid body to be removed
- */
- removeRigidBody: function (rigidBody) {
- var remove = rigidBody;
- if (remove.parent !== this) return;
- remove.awake();
- var js = remove.jointLink;
- while (js != null) {
- var joint = js.joint;
- js = js.next;
- this.removeJoint(joint);
- }
- for (var shape = rigidBody.shapes; shape !== null; shape = shape.next) {
- this.removeShape(shape);
- }
- var prev = remove.prev;
- var next = remove.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.rigidBodies == remove) this.rigidBodies = next;
- remove.prev = null;
- remove.next = null;
- remove.parent = null;
- this.numRigidBodies--;
- },
- getByName: function (name) {
- var result = null;
- var body = this.rigidBodies;
- while (body !== null) {
- if (body.name !== " " && body.name === name) result = body;
- body = body.next;
- }
- var joint = this.joints;
- while (joint !== null) {
- if (joint.name !== "" && joint.name === name) result = joint;
- joint = joint.next;
- }
- return result;
- },
- /**
- * I'll add a shape to the world..
- * Add to the rigid world, and if you add a shape to a rigid body that has been added to the world,
- * Shape will be added to the world automatically, please do not call from outside this method.
- * @param shape Shape you want to add
- */
- addShape: function (shape) {
- if (!shape.parent || !shape.parent.parent) {
- OIMO.Error("World", "It is not possible to be added alone to shape world");
- }
- shape.proxy = this.broadPhase.createProxy(shape);
- shape.updateProxy();
- this.broadPhase.addProxy(shape.proxy);
- },
- /**
- * I will remove the shape from the world.
- * Add to the rigid world, and if you add a shape to a rigid body that has been added to the world,
- * Shape will be added to the world automatically, please do not call from outside this method.
- * @param shape Shape you want to delete
- */
- removeShape: function (shape) {
- this.broadPhase.removeProxy(shape.proxy);
- shape.proxy = null;
- },
- /**
- * I'll add a joint to the world.
- * Joint that has been added will be the operands of each step.
- * @param shape Joint to be added
- */
- addJoint: function (joint) {
- if (joint.parent) {
- OIMO.Error("World", "It is not possible to be added to more than one world one of the joint");
- }
- if (this.joints != null) (this.joints.prev = joint).next = this.joints;
- this.joints = joint;
- joint.parent = this;
- this.numJoints++;
- joint.awake();
- joint.attach();
- },
- /**
- * I will remove the joint from the world.
- * Joint that has been added will be the operands of each step.
- * @param shape Joint to be deleted
- */
- removeJoint: function (joint) {
- var remove = joint;
- var prev = remove.prev;
- var next = remove.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.joints == remove) this.joints = next;
- remove.prev = null;
- remove.next = null;
- this.numJoints--;
- remove.awake();
- remove.detach();
- remove.parent = null;
- },
- worldscale: function (scale) {
- OIMO.WORLD_SCALE = scale || 100;
- OIMO.INV_SCALE = 1 / OIMO.WORLD_SCALE;
- },
- addContact: function (s1, s2) {
- var newContact;
- if (this.unusedContacts !== null) {
- newContact = this.unusedContacts;
- this.unusedContacts = this.unusedContacts.next;
- } else {
- newContact = new OIMO.Contact();
- }
- newContact.attach(s1, s2);
- newContact.detector = this.detectors[s1.type][s2.type];
- if (this.contacts) (this.contacts.prev = newContact).next = this.contacts;
- this.contacts = newContact;
- this.numContacts++;
- },
- removeContact: function (contact) {
- var prev = contact.prev;
- var next = contact.next;
- if (next) next.prev = prev;
- if (prev) prev.next = next;
- if (this.contacts == contact) this.contacts = next;
- contact.prev = null;
- contact.next = null;
- contact.detach();
- contact.next = this.unusedContacts;
- this.unusedContacts = contact;
- this.numContacts--;
- },
- checkContact: function (name1, name2) {
- var n1, n2;
- var contact = this.contacts;
- while (contact !== null) {
- n1 = contact.body1.name || ' ';
- n2 = contact.body2.name || ' ';
- if ((n1 == name1 && n2 == name2) || (n2 == name1 && n1 == name2)) { if (contact.touching) return true; else return false; }
- else contact = contact.next;
- }
- return false;
- },
- callSleep: function (body) {
- if (!body.allowSleep) return false;
- if (body.linearVelocity.lengthSq() > 0.04) return false;
- if (body.angularVelocity.lengthSq() > 0.25) return false;
- return true;
- },
- /**
- * I will proceed only time step seconds time of World.
- */
- step: function () {
- var time0, time1, time2, time3;
- var stat = !this.isNoStat ? true : false;
- if (stat) time0 = OIMO.now();
- var body = this.rigidBodies;
- while (body !== null) {
- body.addedToIsland = false;
- if (body.sleeping) {
- if (
- body.linearVelocity.testZero() ||
- body.angularVelocity.testZero() ||
- body.position.testDiff(body.sleepPosition) ||
- body.orientation.testDiff(body.sleepOrientation)
- ) body.awake(); // awake the body
- }
- body = body.next;
- }
- //------------------------------------------------------
- // UPDATE CONTACT
- //------------------------------------------------------
- // broad phase
- if (stat) time1 = OIMO.now();
- this.broadPhase.detectPairs();
- var pairs = this.broadPhase.pairs;
- var i = this.broadPhase.numPairs;
- //do{
- while (i--) {
- //for(var i=0, l=numPairs; i<l; i++){
- var pair = pairs[i];
- var s1;
- var s2;
- if (pair.shape1.id < pair.shape2.id) {
- s1 = pair.shape1;
- s2 = pair.shape2;
- } else {
- s1 = pair.shape2;
- s2 = pair.shape1;
- }
- var link;
- if (s1.numContacts < s2.numContacts) link = s1.contactLink;
- else link = s2.contactLink;
- var exists = false;
- while (link) {
- var contact = link.contact;
- if (contact.shape1 == s1 && contact.shape2 == s2) {
- contact.persisting = true;
- exists = true;// contact already exists
- break;
- }
- link = link.next;
- }
- if (!exists) {
- this.addContact(s1, s2);
- }
- }// while(i-- >0);
- if (stat) {
- time2 = OIMO.now();
- this.performance.broadPhaseTime = time2 - time1;
- }
- // update & narrow phase
- this.numContactPoints = 0;
- contact = this.contacts;
- while (contact !== null) {
- if (!contact.persisting) {
- if (contact.shape1.aabb.intersectTest(contact.shape2.aabb)) {
- /*var aabb1=contact.shape1.aabb;
- var aabb2=contact.shape2.aabb;
- if(
- aabb1.minX>aabb2.maxX || aabb1.maxX<aabb2.minX ||
- aabb1.minY>aabb2.maxY || aabb1.maxY<aabb2.minY ||
- aabb1.minZ>aabb2.maxZ || aabb1.maxZ<aabb2.minZ
- ){*/
- var next = contact.next;
- this.removeContact(contact);
- contact = next;
- continue;
- }
- }
- var b1 = contact.body1;
- var b2 = contact.body2;
- if (b1.isDynamic && !b1.sleeping || b2.isDynamic && !b2.sleeping) {
- contact.updateManifold();
- }
- this.numContactPoints += contact.manifold.numPoints;
- contact.persisting = false;
- contact.constraint.addedToIsland = false;
- contact = contact.next;
- }
- if (stat) {
- time3 = OIMO.now();
- this.performance.narrowPhaseTime = time3 - time2;
- }
- //------------------------------------------------------
- // SOLVE ISLANDS
- //------------------------------------------------------
- var invTimeStep = 1 / this.timeStep;
- //var body;
- var joint;
- var constraint;
- //var num;
- for (joint = this.joints; joint !== null; joint = joint.next) {
- joint.addedToIsland = false;
- }
- // clear old island array
- this.islandRigidBodies = [];
- this.islandConstraints = [];
- this.islandStack = [];
- // expand island buffers
- /*if(this.maxIslandRigidBodies<this.numRigidBodies){
- this.maxIslandRigidBodies=this.numRigidBodies<<1;
- //this.maxIslandRigidBodies=this.numRigidBodies*2;
- this.islandRigidBodies=[];
- this.islandStack=[];
- this.islandRigidBodies.length = this.maxIslandRigidBodies;
- this.islandStack.length = this.maxIslandRigidBodies;
- }
- var numConstraints=this.numJoints+this.numContacts;
- if(this.maxIslandConstraints<numConstraints){
- this.maxIslandConstraints=numConstraints<<1;
- //this.maxIslandConstraints=numConstraints*2;
- this.islandConstraints=[];
- this.islandConstraints.length = this.maxIslandConstraints;
- }*/
- time1 = OIMO.now();
- this.numIslands = 0;
- // build and solve simulation islands
- for (var base = this.rigidBodies; base !== null; base = base.next) {
- if (base.addedToIsland || base.isStatic || base.sleeping) continue;// ignore
- if (base.isLonely()) {// update single body
- if (base.isDynamic) {
- base.linearVelocity.addTime(this.gravity, this.timeStep);
- /*base.linearVelocity.x+=this.gravity.x*this.timeStep;
- base.linearVelocity.y+=this.gravity.y*this.timeStep;
- base.linearVelocity.z+=this.gravity.z*this.timeStep;*/
- }
- if (this.callSleep(base)) {
- base.sleepTime += this.timeStep;
- if (base.sleepTime > 0.5) base.sleep();
- else base.updatePosition(this.timeStep);
- } else {
- base.sleepTime = 0;
- base.updatePosition(this.timeStep);
- }
- this.numIslands++;
- continue;
- }
- var islandNumRigidBodies = 0;
- var islandNumConstraints = 0;
- var stackCount = 1;
- // add rigid body to stack
- this.islandStack[0] = base;
- base.addedToIsland = true;
- // build an island
- do {
- // get rigid body from stack
- body = this.islandStack[--stackCount];
- this.islandStack[stackCount] = null;
- body.sleeping = false;
- // add rigid body to the island
- this.islandRigidBodies[islandNumRigidBodies++] = body;
- if (body.isStatic) continue;
- // search connections
- for (var cs = body.contactLink; cs !== null; cs = cs.next) {
- var contact = cs.contact;
- constraint = contact.constraint;
- if (constraint.addedToIsland || !contact.touching) continue;// ignore
- // add constraint to the island
- this.islandConstraints[islandNumConstraints++] = constraint;
- constraint.addedToIsland = true;
- var next = cs.body;
- if (next.addedToIsland) continue;
- // add rigid body to stack
- this.islandStack[stackCount++] = next;
- next.addedToIsland = true;
- }
- for (var js = body.jointLink; js !== null; js = js.next) {
- constraint = js.joint;
- if (constraint.addedToIsland) continue;// ignore
- // add constraint to the island
- this.islandConstraints[islandNumConstraints++] = constraint;
- constraint.addedToIsland = true;
- next = js.body;
- if (next.addedToIsland || !next.isDynamic) continue;
- // add rigid body to stack
- this.islandStack[stackCount++] = next;
- next.addedToIsland = true;
- }
- } while (stackCount != 0);
- // update velocities
- var gVel = new OIMO.Vec3().addTime(this.gravity, this.timeStep);
- /*var gx=this.gravity.x*this.timeStep;
- var gy=this.gravity.y*this.timeStep;
- var gz=this.gravity.z*this.timeStep;*/
- var j = islandNumRigidBodies;
- while (j--) {
- //or(var j=0, l=islandNumRigidBodies; j<l; j++){
- body = this.islandRigidBodies[j];
- if (body.isDynamic) {
- body.linearVelocity.addEqual(gVel);
- /*body.linearVelocity.x+=gx;
- body.linearVelocity.y+=gy;
- body.linearVelocity.z+=gz;*/
- }
- }
- // randomizing order
- if (this.enableRandomizer) {
- //for(var j=1, l=islandNumConstraints; j<l; j++){
- j = islandNumConstraints;
- while (j--) {
- if (j !== 0) {
- var swap = (this.randX = (this.randX * this.randA + this.randB & 0x7fffffff)) / 2147483648.0 * j | 0;
- constraint = this.islandConstraints[j];
- this.islandConstraints[j] = this.islandConstraints[swap];
- this.islandConstraints[swap] = constraint;
- }
- }
- }
- // solve contraints
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, l=islandNumConstraints; j<l; j++){
- this.islandConstraints[j].preSolve(this.timeStep, invTimeStep);// pre-solve
- }
- var k = this.numIterations;
- while (k--) {
- //for(var k=0, l=this.numIterations; k<l; k++){
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, m=islandNumConstraints; j<m; j++){
- this.islandConstraints[j].solve();// main-solve
- }
- }
- j = islandNumConstraints;
- while (j--) {
- //for(j=0, l=islandNumConstraints; j<l; j++){
- this.islandConstraints[j].postSolve();// post-solve
- this.islandConstraints[j] = null;// gc
- }
- // sleeping check
- var sleepTime = 10;
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- body = this.islandRigidBodies[j];
- if (this.callSleep(body)) {
- body.sleepTime += this.timeStep;
- if (body.sleepTime < sleepTime) sleepTime = body.sleepTime;
- } else {
- body.sleepTime = 0;
- sleepTime = 0;
- continue;
- }
- }
- if (sleepTime > 0.5) {
- // sleep the island
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- this.islandRigidBodies[j].sleep();
- this.islandRigidBodies[j] = null;// gc
- }
- } else {
- // update positions
- j = islandNumRigidBodies;
- while (j--) {
- //for(j=0, l=islandNumRigidBodies;j<l;j++){
- this.islandRigidBodies[j].updatePosition(this.timeStep);
- this.islandRigidBodies[j] = null;// gc
- }
- }
- this.numIslands++;
- }
- if (stat) {
- time2 = OIMO.now();
- this.performance.solvingTime = time2 - time1;
- //------------------------------------------------------
- // END SIMULATION
- //------------------------------------------------------
- time2 = OIMO.now();
- // fps update
- this.performance.upfps();
- this.performance.totalTime = time2 - time0;
- }
- }
- }
- /**
- * The class of rigid body.
- * Rigid body has the shape of a single or multiple collision processing,
- * I can set the parameters individually.
- * @author saharan
- */
- OIMO.RigidBody = function (x, y, z, rad, ax, ay, az) {
- this.name = " ";
- // The maximum number of shapes that can be added to a one rigid.
- this.MAX_SHAPES = 64;//64;
- this.prev = null;
- this.next = null;
- // I represent the kind of rigid body.
- // Please do not change from the outside this variable.
- // If you want to change the type of rigid body, always
- // Please specify the type you want to set the arguments of setupMass method.
- this.type = OIMO.BODY_NULL;
- this.massInfo = new OIMO.MassInfo();
- // It is the world coordinate of the center of gravity.
- this.position = new OIMO.Vec3(x, y, z);
- this.orientation = this.rotationAxisToQuad(rad || 0, ax || 0, ay || 0, az || 0);
- this.newPosition = new OIMO.Vec3();
- this.controlPos = false;
- this.newOrientation = new OIMO.Quat();
- this.newRotation = new OIMO.Vec3();
- this.currentRotation = new OIMO.Vec3();
- this.controlRot = false;
- this.controlRotInTime = false;
- // Is the translational velocity.
- this.linearVelocity = new OIMO.Vec3();
- // Is the angular velocity.
- this.angularVelocity = new OIMO.Vec3();
- // return matrix for three.js
- this.matrix = new OIMO.Mat44();
- //--------------------------------------------
- // Please do not change from the outside this variables.
- //--------------------------------------------
- // It is a world that rigid body has been added.
- this.parent = null;
- this.contactLink = null;
- this.numContacts = 0;
- // An array of shapes that are included in the rigid body.
- this.shapes = null;
- // The number of shapes that are included in the rigid body.
- this.numShapes = 0;
- // It is the link array of joint that is connected to the rigid body.
- this.jointLink = null;
- // The number of joints that are connected to the rigid body.
- this.numJoints = 0;
- // It is the world coordinate of the center of gravity in the sleep just before.
- this.sleepPosition = new OIMO.Vec3();
- // It is a quaternion that represents the attitude of sleep just before.
- this.sleepOrientation = new OIMO.Quat();
- // I will show this rigid body to determine whether it is a rigid body static.
- this.isStatic = false;
- // I indicates that this rigid body to determine whether it is a rigid body dynamic.
- this.isDynamic = false;
- // It is a rotation matrix representing the orientation.
- this.rotation = new OIMO.Mat33();
- //--------------------------------------------
- // It will be recalculated automatically from the shape, which is included.
- //--------------------------------------------
- // This is the weight.
- this.mass = NaN;
- // It is the reciprocal of the mass.
- this.inverseMass = NaN;
- // It is the inverse of the inertia tensor in the world system.
- this.inverseInertia = new OIMO.Mat33();
- // It is the inertia tensor in the initial state.
- this.localInertia = new OIMO.Mat33();
- // It is the inverse of the inertia tensor in the initial state.
- this.inverseLocalInertia = new OIMO.Mat33();
- // I indicates rigid body whether it has been added to the simulation Island.
- this.addedToIsland = false;
- // It shows how to sleep rigid body.
- this.allowSleep = true;
- // This is the time from when the rigid body at rest.
- this.sleepTime = 0;
- // I shows rigid body to determine whether it is a sleep state.
- this.sleeping = false;
- };
- OIMO.RigidBody.prototype = {
- constructor: OIMO.RigidBody,
- /**
- * I'll add a shape to rigid body.
- * If you add a shape, please call the setupMass method to step up to the start of the next.
- * @param shape shape to Add
- */
- addShape: function (shape) {
- if (shape.parent) OIMO.Error("RigidBody", "It is not possible that you add to the multi-rigid body the shape of one");
- if (this.shapes != null) (this.shapes.prev = shape).next = this.shapes;
- this.shapes = shape;
- shape.parent = this;
- if (this.parent) this.parent.addShape(shape);
- this.numShapes++;
- },
- /**
- * I will delete the shape from the rigid body.
- * If you delete a shape, please call the setupMass method to step up to the start of the next.
- * @param shape shape to Delete
- */
- removeShape: function (shape) {
- var remove = shape;
- if (remove.parent != this) return;
- var prev = remove.prev;
- var next = remove.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.shapes == remove) this.shapes = next;
- remove.prev = null;
- remove.next = null;
- remove.parent = null;
- if (this.parent) this.parent.removeShape(remove);
- this.numShapes--;
- },
- remove: function () {
- this.dispose();
- },
- dispose: function () {
- this.parent.removeRigidBody(this);
- },
- checkContact: function (name) {
- this.parent.checkContact(this.name, name);
- },
- /**
- * Calulates mass datas(center of gravity, mass, moment inertia, etc...).
- * If the parameter type is set to BODY_STATIC, the rigid body will be fixed to the space.
- * If the parameter adjustPosition is set to true, the shapes' relative positions and
- * the rigid body's position will be adjusted to the center of gravity.
- * @param type
- * @param adjustPosition
- */
- setupMass: function (type, AdjustPosition) {
- var adjustPosition = (AdjustPosition !== undefined) ? AdjustPosition : true;
- this.type = type || OIMO.BODY_DYNAMIC;
- this.isDynamic = this.type == OIMO.BODY_DYNAMIC;
- this.isStatic = this.type == OIMO.BODY_STATIC;
- this.mass = 0;
- this.localInertia.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
- var te = this.localInertia.elements;
- //
- var tmpM = new OIMO.Mat33();
- var tmpV = new OIMO.Vec3();
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.calculateMassInfo(this.massInfo);
- var shapeMass = this.massInfo.mass;
- var relX = shape.relativePosition.x;
- var relY = shape.relativePosition.y;
- var relZ = shape.relativePosition.z;
- /*tmpV.x+=relX*shapeMass;
- tmpV.y+=relY*shapeMass;
- tmpV.z+=relZ*shapeMass;*/
- tmpV.addScale(shape.relativePosition, shapeMass);
- this.mass += shapeMass;
- this.rotateInertia(shape.relativeRotation, this.massInfo.inertia, tmpM);
- this.localInertia.addEqual(tmpM);
- // add offset inertia
- te[0] += shapeMass * (relY * relY + relZ * relZ);
- te[4] += shapeMass * (relX * relX + relZ * relZ);
- te[8] += shapeMass * (relX * relX + relY * relY);
- var xy = shapeMass * relX * relY;
- var yz = shapeMass * relY * relZ;
- var zx = shapeMass * relZ * relX;
- te[1] -= xy;
- te[3] -= xy;
- te[2] -= yz;
- te[6] -= yz;
- te[5] -= zx;
- te[7] -= zx;
- }
- this.inverseMass = 1 / this.mass;
- tmpV.scaleEqual(this.inverseMass);
- if (adjustPosition) {
- this.position.addEqual(tmpV);
- for (shape = this.shapes; shape != null; shape = shape.next) {
- shape.relativePosition.subEqual(tmpV);
- }
- // subtract offset inertia
- relX = tmpV.x;
- relY = tmpV.y;
- relZ = tmpV.z;
- //var te = this.localInertia.elements;
- te[0] -= this.mass * (relY * relY + relZ * relZ);
- te[4] -= this.mass * (relX * relX + relZ * relZ);
- te[8] -= this.mass * (relX * relX + relY * relY);
- xy = this.mass * relX * relY;
- yz = this.mass * relY * relZ;
- zx = this.mass * relZ * relX;
- te[1] += xy;
- te[3] += xy;
- te[2] += yz;
- te[6] += yz;
- te[5] += zx;
- te[7] += zx;
- }
- this.inverseLocalInertia.invert(this.localInertia);
- if (this.type == OIMO.BODY_STATIC) {
- this.inverseMass = 0;
- this.inverseLocalInertia.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
- }
- this.syncShapes();
- this.awake();
- },
- /**
- * Awake the rigid body.
- */
- awake: function () {
- if (!this.allowSleep || !this.sleeping) return;
- this.sleeping = false;
- this.sleepTime = 0;
- // awake connected constraints
- var cs = this.contactLink;
- while (cs != null) {
- cs.body.sleepTime = 0;
- cs.body.sleeping = false;
- cs = cs.next;
- }
- var js = this.jointLink;
- while (js != null) {
- js.body.sleepTime = 0;
- js.body.sleeping = false;
- js = js.next;
- }
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.updateProxy();
- }
- },
- /**
- * Sleep the rigid body.
- */
- sleep: function () {
- if (!this.allowSleep || this.sleeping) return;
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- this.sleepPosition.copy(this.position);
- this.sleepOrientation.copy(this.orientation);
- /*this.linearVelocity.x=0;
- this.linearVelocity.y=0;
- this.linearVelocity.z=0;
- this.angularVelocity.x=0;
- this.angularVelocity.y=0;
- this.angularVelocity.z=0;
- this.sleepPosition.x=this.position.x;
- this.sleepPosition.y=this.position.y;
- this.sleepPosition.z=this.position.z;*/
- /*this.sleepOrientation.s=this.orientation.s;
- this.sleepOrientation.x=this.orientation.x;
- this.sleepOrientation.y=this.orientation.y;
- this.sleepOrientation.z=this.orientation.z;*/
- this.sleepTime = 0;
- this.sleeping = true;
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- shape.updateProxy();
- }
- },
- /**
- * Get whether the rigid body has not any connection with others.
- * @return
- */
- isLonely: function () {
- return this.numJoints == 0 && this.numContacts == 0;
- },
- /**
- * The time integration of the motion of a rigid body, you can update the information such as the shape.
- * This method is invoked automatically when calling the step of the World,
- * There is no need to call from outside usually.
- * @param timeStep time
- */
- updatePosition: function (timeStep) {
- switch (this.type) {
- case OIMO.BODY_STATIC:
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- // ONLY FOR TEST
- if (this.controlPos) {
- this.position.copy(this.newPosition);
- this.controlPos = false;
- }
- if (this.controlRot) {
- this.orientation.copy(this.newOrientation);
- this.controlRot = false;
- }
- /*this.linearVelocity.x=0;
- this.linearVelocity.y=0;
- this.linearVelocity.z=0;
- this.angularVelocity.x=0;
- this.angularVelocity.y=0;
- this.angularVelocity.z=0;*/
- break;
- case OIMO.BODY_DYNAMIC:
- if (this.controlPos) {
- this.angularVelocity.set(0, 0, 0);
- this.linearVelocity.set(0, 0, 0);
- this.linearVelocity.x = (this.newPosition.x - this.position.x) / timeStep;
- this.linearVelocity.y = (this.newPosition.y - this.position.y) / timeStep;
- this.linearVelocity.z = (this.newPosition.z - this.position.z) / timeStep;
- this.controlPos = false;
- }
- if (this.controlRot) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation.copy(this.newOrientation);
- //var t=timeStep//*0.5;
- //var q = new OIMO.Quat();
- //q.sub(this.newOrientation, this.orientation);
- //q.normalize(q);
- /*q.s = (this.newOrientation.s - this.orientation.s)/t;
- q.x = (this.newOrientation.x - this.orientation.x)/t;
- q.y = (this.newOrientation.y - this.orientation.y)/t;
- q.z = (this.newOrientation.z - this.orientation.z)/t;*/
- //this.angularVelocity.applyQuaternion(q);
- //this.angularVelocity.x = this.angularVelocity.x/t;
- //this.angularVelocity.y = this.angularVelocity.y/t;
- //this.angularVelocity.z = this.angularVelocity.z/t;
- this.controlRot = false;
- }
- this.position.addTime(this.linearVelocity, timeStep);
- this.orientation.addTime(this.angularVelocity, timeStep);
- break;
- default: OIMO.Error("RigidBody", "Invalid type.");
- }
- this.syncShapes();
- },
- rotateInertia: function (rot, inertia, out) {
- var tm1 = rot.elements;
- var tm2 = inertia.elements;
- var a0 = tm1[0], a3 = tm1[3], a6 = tm1[6];
- var a1 = tm1[1], a4 = tm1[4], a7 = tm1[7];
- var a2 = tm1[2], a5 = tm1[5], a8 = tm1[8];
- var b0 = tm2[0], b3 = tm2[3], b6 = tm2[6];
- var b1 = tm2[1], b4 = tm2[4], b7 = tm2[7];
- var b2 = tm2[2], b5 = tm2[5], b8 = tm2[8];
- var e00 = a0 * b0 + a1 * b3 + a2 * b6;
- var e01 = a0 * b1 + a1 * b4 + a2 * b7;
- var e02 = a0 * b2 + a1 * b5 + a2 * b8;
- var e10 = a3 * b0 + a4 * b3 + a5 * b6;
- var e11 = a3 * b1 + a4 * b4 + a5 * b7;
- var e12 = a3 * b2 + a4 * b5 + a5 * b8;
- var e20 = a6 * b0 + a7 * b3 + a8 * b6;
- var e21 = a6 * b1 + a7 * b4 + a8 * b7;
- var e22 = a6 * b2 + a7 * b5 + a8 * b8;
- var oe = out.elements;
- oe[0] = e00 * a0 + e01 * a1 + e02 * a2;
- oe[1] = e00 * a3 + e01 * a4 + e02 * a5;
- oe[2] = e00 * a6 + e01 * a7 + e02 * a8;
- oe[3] = e10 * a0 + e11 * a1 + e12 * a2;
- oe[4] = e10 * a3 + e11 * a4 + e12 * a5;
- oe[5] = e10 * a6 + e11 * a7 + e12 * a8;
- oe[6] = e20 * a0 + e21 * a1 + e22 * a2;
- oe[7] = e20 * a3 + e21 * a4 + e22 * a5;
- oe[8] = e20 * a6 + e21 * a7 + e22 * a8;
- },
- syncShapes: function () {
- var s = this.orientation.s;
- var x = this.orientation.x;
- var y = this.orientation.y;
- var z = this.orientation.z;
- var x2 = 2 * x;
- var y2 = 2 * y;
- var z2 = 2 * z;
- var xx = x * x2;
- var yy = y * y2;
- var zz = z * z2;
- var xy = x * y2;
- var yz = y * z2;
- var xz = x * z2;
- var sx = s * x2;
- var sy = s * y2;
- var sz = s * z2;
- var tr = this.rotation.elements;
- tr[0] = 1 - yy - zz;
- tr[1] = xy - sz;
- tr[2] = xz + sy;
- tr[3] = xy + sz;
- tr[4] = 1 - xx - zz;
- tr[5] = yz - sx;
- tr[6] = xz - sy;
- tr[7] = yz + sx;
- tr[8] = 1 - xx - yy;
- this.rotateInertia(this.rotation, this.inverseLocalInertia, this.inverseInertia);
- for (var shape = this.shapes; shape != null; shape = shape.next) {
- //var relPos=shape.relativePosition;
- //var relRot=shape.relativeRotation;
- //var rot=shape.rotation;
- /*var lx=relPos.x;
- var ly=relPos.y;
- var lz=relPos.z;
- shape.position.x=this.position.x+lx*tr[0]+ly*tr[1]+lz*tr[2];
- shape.position.y=this.position.y+lx*tr[3]+ly*tr[4]+lz*tr[5];
- shape.position.z=this.position.z+lx*tr[6]+ly*tr[7]+lz*tr[8];*/
- shape.position.mul(this.position, shape.relativePosition, this.rotation);
- //shape.rotation.mul(shape.relativeRotation,this.rotation);
- // add by QuaziKb
- shape.rotation.mul(this.rotation, shape.relativeRotation);
- shape.updateProxy();
- }
- },
- applyImpulse: function (position, force) {
- this.linearVelocity.addScale(force, this.inverseMass);
- /*this.linearVelocity.x+=force.x*this.inverseMass;
- this.linearVelocity.y+=force.y*this.inverseMass;
- this.linearVelocity.z+=force.z*this.inverseMass;*/
- var rel = new OIMO.Vec3();
- rel.sub(position, this.position).cross(rel, force).mulMat(this.inverseInertia, rel);
- this.angularVelocity.addEqual(rel);
- /*this.angularVelocity.x+=rel.x;
- this.angularVelocity.y+=rel.y;
- this.angularVelocity.z+=rel.z;*/
- },
- //---------------------------------------------
- //
- // FOR THREE JS
- //
- //---------------------------------------------
- rotationVectToQuad: function (rot) {
- var r = OIMO.EulerToAxis(rot.x * OIMO.degtorad, rot.y * OIMO.degtorad, rot.z * OIMO.degtorad);
- return this.rotationAxisToQuad(r[0], r[1], r[2], r[3]);
- },
- rotationAxisToQuad: function (rad, ax, ay, az) { // in radian
- var len = ax * ax + ay * ay + az * az;
- if (len > 0) {
- len = 1 / OIMO.sqrt(len);
- ax *= len;
- ay *= len;
- az *= len;
- }
- var sin = OIMO.sin(rad * 0.5);
- var cos = OIMO.cos(rad * 0.5);
- return new OIMO.Quat(cos, sin * ax, sin * ay, sin * az);
- },
- //---------------------------------------------
- // SET DYNAMIQUE POSITION AND ROTATION
- //---------------------------------------------
- setPosition: function (pos) {
- this.newPosition.copy(pos).multiplyScalar(OIMO.INV_SCALE);
- //this.newPosition.set(pos.x*OIMO.INV_SCALE,pos.y*OIMO.INV_SCALE,pos.z*OIMO.INV_SCALE);
- this.controlPos = true;
- },
- setQuaternion: function (q) {
- //if(this.type == this.BODY_STATIC)this.orientation.init(q.w,q.x,q.y,q.z);
- this.newOrientation.set(q.x, q.y, q.z, q.w);
- this.controlRot = true;
- },
- setRotation: function (rot) {
- this.newOrientation = this.rotationVectToQuad(rot);
- this.controlRot = true;
- },
- //---------------------------------------------
- // RESET DYNAMIQUE POSITION AND ROTATION
- //---------------------------------------------
- resetPosition: function (x, y, z) {
- this.linearVelocity.set(0, 0, 0);
- this.angularVelocity.set(0, 0, 0);
- this.position.set(x, y, z).multiplyScalar(OIMO.INV_SCALE);
- //this.position.set( x*OIMO.INV_SCALE, y*OIMO.INV_SCALE, z*OIMO.INV_SCALE );
- this.awake();
- },
- resetQuaternion: function (q) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation = new OIMO.Quat(q.w, q.x, q.y, q.z);
- this.awake();
- },
- resetRotation: function (x, y, z) {
- this.angularVelocity.set(0, 0, 0);
- this.orientation = this.rotationVectToQuad(new OIMO.Vec3(x, y, z));
- this.awake();
- },
- //---------------------------------------------
- // GET POSITION AND ROTATION
- //---------------------------------------------
- getPosition: function () {
- return new OIMO.Vec3().scale(this.position, OIMO.WORLD_SCALE);
- },
- getRotation: function () {
- return new OIMO.Euler().setFromRotationMatrix(this.rotation);
- },
- getQuaternion: function () {
- return new OIMO.Quaternion().setFromRotationMatrix(this.rotation);
- },
- getMatrix: function () {
- var m = this.matrix.elements;
- var r, p;
- if (!this.sleeping) {
- // rotation matrix
- r = this.rotation.elements;
- m[0] = r[0]; m[1] = r[3]; m[2] = r[6]; m[3] = 0;
- m[4] = r[1]; m[5] = r[4]; m[6] = r[7]; m[7] = 0;
- m[8] = r[2]; m[9] = r[5]; m[10] = r[8]; m[11] = 0;
- // position matrix
- p = this.position;
- m[12] = p.x * OIMO.WORLD_SCALE;
- m[13] = p.y * OIMO.WORLD_SCALE;
- m[14] = p.z * OIMO.WORLD_SCALE;
- // sleep or not ?
- m[15] = 0;
- } else {
- m[15] = 1;
- }
- return m;
- }
- };
- /**
- * The main class of body.
- * is for simplify creation process and data access of rigidRody
- * Rigid body has the shape of a single or multiple collision processing,
- * all setting in object
- *
- * @author loth
- */
- OIMO.Body = function (Obj) {
- var obj = Obj || {};
- if (!obj.world) return;
- if (obj.type === undefined) obj.type = "box";
- this.name = obj.name || '';
- // obsolete use world.add(obj)
- this.body = obj.world.add(obj);
- /*
- // the world where i am
- this.parent = obj.world;
-
- // Yep my name
- this.name = obj.name || '';
-
- // I'm dynamique or not
- var move = obj.move || false;
-
- // I can sleep or not
- var noSleep = obj.noSleep || false;
-
- // My start position
- var p = obj.pos || [0,0,0];
- p = p.map(function(x) { return x * OIMO.INV_SCALE; });
-
- // My size
- var s = obj.size || [1,1,1];
- s = s.map(function(x) { return x * OIMO.INV_SCALE; });
-
- // My rotation in degre
- var rot = obj.rot || [0,0,0];
- rot = rot.map(function(x) { return x * OIMO.TO_RAD; });
- var r = [];
- for (var i=0; i<rot.length/3; i++){
- var tmp = OIMO.EulerToAxis(rot[i+0], rot[i+1], rot[i+2]);
- r.push(tmp[0]); r.push(tmp[1]); r.push(tmp[2]); r.push(tmp[3]);
- }
-
- // My physics setting
- var sc = obj.sc || new OIMO.ShapeConfig();
- if(obj.config){
- // The density of the shape.
- sc.density = obj.config[0] || 1;
- // The coefficient of friction of the shape.
- sc.friction = obj.config[1] || 0.4;
- // The coefficient of restitution of the shape.
- sc.restitution = obj.config[2] || 0.2;
- // The bits of the collision groups to which the shape belongs.
- sc.belongsTo = obj.config[3] || 1;
- // The bits of the collision groups with which the shape collides.
- sc.collidesWith = obj.config[4] || 0xffffffff;
- }
-
- if(obj.massPos){
- obj.massPos = obj.massPos.map(function(x) { return x * OIMO.INV_SCALE; });
- sc.relativePosition.init(obj.massPos[0], obj.massPos[1], obj.massPos[2]);
- }
- if(obj.massRot){
- obj.massRot = obj.massRot.map(function(x) { return x * OIMO.TO_RAD; });
- sc.relativeRotation = OIMO.EulerToMatrix(obj.massRot[0], obj.massRot[1], obj.massRot[2]);
- }
-
- // My rigidbody
- this.body = new OIMO.RigidBody(p[0], p[1], p[2], r[0], r[1], r[2], r[3]);
-
- // My shapes
- var shapes = [];
- var type = obj.type || "box";
- if( typeof type === 'string' ) type = [type];// single shape
-
- var n, n2;
- for(var i=0; i<type.length; i++){
- n = i*3;
- n2 = i*4;
- switch(type[i]){
- case "sphere": shapes[i] = new OIMO.SphereShape(sc, s[n+0]); break;
- case "cylinder": shapes[i] = new OIMO.BoxShape(sc, s[n+0], s[n+1], s[n+2]); break; // fake cylinder
- case "box": shapes[i] = new OIMO.BoxShape(sc, s[n+0], s[n+1], s[n+2]); break;
- }
- this.body.addShape(shapes[i]);
- if(i>0){
- //shapes[i].position.init(p[0]+p[n+0], p[1]+p[n+1], p[2]+p[n+2] );
- shapes[i].relativePosition = new OIMO.Vec3( p[n+0], p[n+1], p[n+2] );
- if(r[n2+0]) shapes[i].relativeRotation = [ r[n2+0], r[n2+1], r[n2+2], r[n2+3] ];
- }
- }
-
- // I'm static or i move
- if(move){
- if(obj.massPos || obj.massRot)this.body.setupMass(0x1, false);
- else this.body.setupMass(0x1, true);
- if(noSleep) this.body.allowSleep = false;
- else this.body.allowSleep = true;
- } else {
- this.body.setupMass(0x2);
- }
-
- this.body.name = this.name;
- this.sleeping = this.body.sleeping;
-
- // finaly add to physics world
- this.parent.addRigidBody(this.body);*/
- }
- OIMO.Body.prototype = {
- constructor: OIMO.Body,
- // SET
- setPosition: function (pos) {
- this.body.setPosition(pos);
- },
- setQuaternion: function (q) {
- this.body.setQuaternion(q);
- },
- setRotation: function (rot) {
- this.body.setRotation(rot);
- },
- // GET
- getPosition: function () {
- return this.body.getPosition();
- },
- getRotation: function () {
- return this.body.getRotation();
- },
- getQuaternion: function () {
- return this.body.getQuaternion();
- },
- getMatrix: function () {
- return this.body.getMatrix();
- },
- getSleep: function () {
- return this.body.sleeping;
- },
- // RESET
- resetPosition: function (x, y, z) {
- this.body.resetPosition(x, y, z);
- },
- resetRotation: function (x, y, z) {
- this.body.resetRotation(x, y, z);
- },
- // force wakeup
- awake: function () {
- this.body.awake();
- },
- // remove rigidbody
- remove: function () {
- this.body.dispose();
- //this.parent.removeRigidBody(this.body);
- },
- // test if this object hit another
- checkContact: function (name) {
- this.body.checkContact(name);
- //this.parent.checkContact(this.name, name);
- }
- }
- /**
- * The main class of link.
- * is for simplify creation process and data access of Joint
- * all setting in object
- *
- * @author loth
- */
- OIMO.Link = function (Obj) {
- var obj = Obj || {};
- if (!obj.world) return;
- if (obj.type === undefined) obj.type = "jointHinge";
- this.name = obj.name || '';
- // obsolete use world.add(obj)
- this.joint = obj.world.add(obj);
- // the world where i am
- /*this.parent = obj.world;
- this.name = obj.name || '';
- var type = obj.type || "jointHinge";
- var axe1 = obj.axe1 || [1,0,0];
- var axe2 = obj.axe2 || [1,0,0];
- var pos1 = obj.pos1 || [0,0,0];
- var pos2 = obj.pos2 || [0,0,0];
- pos1 = pos1.map(function(x){ return x * OIMO.INV_SCALE; });
- pos2 = pos2.map(function(x){ return x * OIMO.INV_SCALE; });
- var min, max;
- if(type==="jointDistance"){
- min = obj.min || 0;
- max = obj.max || 10;
- min = min*OIMO.INV_SCALE;
- max = max*OIMO.INV_SCALE;
- }else{
- min = obj.min || 57.29578;
- max = obj.max || 0;
- min = min*OIMO.TO_RAD;
- max = max*OIMO.TO_RAD;
- }
- var limit = obj.limit || null;
- var spring = obj.spring || null;
- var motor = obj.motor || null;
- // joint setting
- var jc = new OIMO.JointConfig();
- jc.allowCollision = obj.collision || false;;
- jc.localAxis1.init(axe1[0], axe1[1], axe1[2]);
- jc.localAxis2.init(axe2[0], axe2[1], axe2[2]);
- jc.localAnchorPoint1.init(pos1[0], pos1[1], pos1[2]);
- jc.localAnchorPoint2.init(pos2[0], pos2[1], pos2[2]);
- if (typeof obj.body1 == 'string' || obj.body1 instanceof String) obj.body1 = obj.world.getByName(obj.body1);
- if (typeof obj.body2 == 'string' || obj.body2 instanceof String) obj.body2 = obj.world.getByName(obj.body2);
- jc.body1 = obj.body1;
- jc.body2 = obj.body2;
-
- switch(type){
- case "jointDistance": this.joint = new OIMO.DistanceJoint(jc, min, max);
- if(spring !== null) this.joint.limitMotor.setSpring(spring[0], spring[1]);
- if(motor !== null) this.joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointHinge": this.joint = new OIMO.HingeJoint(jc, min, max);
- if(spring !== null) this.joint.limitMotor.setSpring(spring[0], spring[1]);// soften the joint ex: 100, 0.2
- if(motor !== null) this.joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointPrisme": this.joint = new OIMO.PrismaticJoint(jc, min, max); break;
- case "jointSlide": this.joint = new OIMO.SliderJoint(jc, min, max); break;
- case "jointBall": this.joint = new OIMO.BallAndSocketJoint(jc); break;
- case "jointWheel": this.joint = new OIMO.WheelJoint(jc);
- if(limit !== null) this.joint.rotationalLimitMotor1.setLimit(limit[0], limit[1]);
- if(spring !== null) this.joint.rotationalLimitMotor1.setSpring(spring[0], spring[1]);
- if(motor !== null) this.joint.rotationalLimitMotor1.setSpring(motor[0], motor[1]);
- break;
- }
- this.joint.name = this.name;
-
- // finaly add to physics world
- this.parent.addJoint(this.joint);*/
- }
- OIMO.Link.prototype = {
- constructor: OIMO.Link,
- getPosition: function () {
- // array of two vect3 [point1, point2]
- return this.joint.getPosition();
- },
- getMatrix: function () {
- return this.joint.getMatrix();
- },
- // remove joint
- remove: function () {
- this.joint.dispose();
- //this.parent.removeJoint(this.joint);
- },
- // force wakeup linked body
- awake: function () {
- this.joint.awake();
- }
- }
- /**
- * The Dictionary class for testing
- * @author lo-th
- */
- OIMO.Dictionary = function () {
- this.data = {};
- this.keys = [];
- };
- OIMO.Dictionary.prototype = {
- constructor: OIMO.Dictionary,
- set: function (value) {
- var key = value.id;
- if (!this.get[key]) this.keys.push(key);
- this.data[key] = value;
- },
- get: function (id) {
- return this.data[id];
- },
- del: function (value) {
- var k = this.keys;
- var n = k.indexOf(value.id);
- if (n > -1) {
- delete this.data[k[n]];
- k.splice(n, 1);
- }
- },
- reset: function () {
- var data = this.data, keys = this.keys, key;
- while (keys.length > 0) {
- key = keys.pop();
- delete data[key];
- }
- }
- };
- OIMO.Performance = function (world) {
- this.parent = world;
- this.infos = new OIMO_ARRAY_TYPE(13);
- this.f = [0, 0, 0];
- this.types = ['None', 'BruteForce', 'Sweep & Prune', 'Bounding Volume Tree'];
- this.broadPhase = this.types[this.parent.broadPhase.types];
- this.version = OIMO.REVISION;
- this.fps = 0;
- this.broadPhaseTime = 0;
- this.narrowPhaseTime = 0;
- this.solvingTime = 0;
- //this.updatingTime = 0;
- this.totalTime = 0;
- };
- OIMO.Performance.prototype = {
- upfps: function () {
- this.f[1] = Date.now();
- if (this.f[1] - 1000 > this.f[0]) { this.f[0] = this.f[1]; this.fps = this.f[2]; this.f[2] = 0; } this.f[2]++;
- },
- updatingTime: function () {
- return OIMO.fix(this.totalTime - (this.broadPhaseTime + this.narrowPhaseTime + this.solvingTime));
- },
- show: function () {
- var info = [
- "Oimo.js " + this.version + "<br>",
- this.broadPhase + "<br><br>",
- "FPS: " + this.fps + " fps<br><br>",
- "rigidbody " + this.parent.numRigidBodies + "<br>",
- "contact " + this.parent.numContacts + "<br>",
- "ct-point " + this.parent.numContactPoints + "<br>",
- "paircheck " + this.parent.broadPhase.numPairChecks + "<br>",
- "island " + this.parent.numIslands + "<br><br>",
- "Time in milliseconde<br><br>",
- "broad-phase " + OIMO.fix(this.broadPhaseTime) + "<br>",
- "narrow-phase " + OIMO.fix(this.narrowPhaseTime) + "<br>",
- "solving " + OIMO.fix(this.solvingTime) + "<br>",
- "total " + OIMO.fix(this.totalTime) + "<br>",
- "updating " + this.updatingTime() + "<br>"
- ].join("\n");
- return info;
- },
- toArray: function () {
- this.infos[0] = this.parent.broadPhase.types;
- this.infos[1] = this.parent.numRigidBodies;
- this.infos[2] = this.parent.numContacts;
- this.infos[3] = this.parent.broadPhase.numPairChecks;
- this.infos[4] = this.parent.numContactPoints;
- this.infos[5] = this.parent.numIslands;
- this.infos[6] = this.broadPhaseTime;
- this.infos[7] = this.narrowPhaseTime;
- this.infos[8] = this.solvingTime;
- this.infos[9] = this.updatingTime();
- this.infos[10] = this.totalTime;
- this.infos[11] = this.fps;
- return this.infos;
- }
- };
- OIMO.Mat44 = function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
- this.elements = new OIMO_ARRAY_TYPE(16);
- var te = this.elements;
- te[0] = (n11 !== undefined) ? n11 : 1; te[4] = n12 || 0; te[8] = n13 || 0; te[12] = n14 || 0;
- te[1] = n21 || 0; te[5] = (n22 !== undefined) ? n22 : 1; te[9] = n23 || 0; te[13] = n24 || 0;
- te[2] = n31 || 0; te[6] = n32 || 0; te[10] = (n33 !== undefined) ? n33 : 1; te[14] = n34 || 0;
- te[3] = n41 || 0; te[7] = n42 || 0; te[11] = n43 || 0; te[15] = (n44 !== undefined) ? n44 : 1;
- };
- OIMO.Mat44.prototype = {
- constructor: OIMO.Mat44,
- set: function (n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
- var te = this.elements;
- te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
- te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
- te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
- te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
- return this;
- }/*,
- extractRotation: function () {
- var v1 = new THREE.Vector3();
- return function ( m ) {
- var te = this.elements;
- var me = m.elements;
- var scaleX = 1 / v1.set( me[ 0 ], me[ 1 ], me[ 2 ] ).length();
- var scaleY = 1 / v1.set( me[ 4 ], me[ 5 ], me[ 6 ] ).length();
- var scaleZ = 1 / v1.set( me[ 8 ], me[ 9 ], me[ 10 ] ).length();
- te[ 0 ] = me[ 0 ] * scaleX;
- te[ 1 ] = me[ 1 ] * scaleX;
- te[ 2 ] = me[ 2 ] * scaleX;
- te[ 4 ] = me[ 4 ] * scaleY;
- te[ 5 ] = me[ 5 ] * scaleY;
- te[ 6 ] = me[ 6 ] * scaleY;
- te[ 8 ] = me[ 8 ] * scaleZ;
- te[ 9 ] = me[ 9 ] * scaleZ;
- te[ 10 ] = me[ 10 ] * scaleZ;
- return this;
- };
- }() */
- }
- OIMO.Mat33 = function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- this.elements = new OIMO_ARRAY_TYPE(9);
- var te = this.elements;
- this.init(
- (e00 !== undefined) ? e00 : 1, e01 || 0, e02 || 0,
- e10 || 0, (e11 !== undefined) ? e11 : 1, e12 || 0,
- e20 || 0, e21 || 0, (e22 !== undefined) ? e22 : 1
- );
- };
- OIMO.Mat33.prototype = {
- constructor: OIMO.Mat33,
- set: function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- var te = this.elements;
- te[0] = e00; te[1] = e01; te[2] = e02;
- te[3] = e10; te[4] = e11; te[5] = e12;
- te[6] = e20; te[7] = e21; te[8] = e22;
- return this;
- },
- init: function (e00, e01, e02, e10, e11, e12, e20, e21, e22) {
- var te = this.elements;
- te[0] = e00; te[1] = e01; te[2] = e02;
- te[3] = e10; te[4] = e11; te[5] = e12;
- te[6] = e20; te[7] = e21; te[8] = e22;
- return this;
- },
- multiply: function (s) {
- var te = this.elements;
- te[0] *= s; te[1] *= s; te[2] *= s;
- te[3] *= s; te[4] *= s; te[5] *= s;
- te[6] *= s; te[7] *= s; te[8] *= s;
- return this;
- },
- add: function (m1, m2) {
- var te = this.elements, tem1 = m1.elements, tem2 = m2.elements;
- te[0] = tem1[0] + tem2[0]; te[1] = tem1[1] + tem2[1]; te[2] = tem1[2] + tem2[2];
- te[3] = tem1[3] + tem2[3]; te[4] = tem1[4] + tem2[4]; te[5] = tem1[5] + tem2[5];
- te[6] = tem1[6] + tem2[6]; te[7] = tem1[7] + tem2[7]; te[8] = tem1[8] + tem2[8];
- return this;
- },
- addEqual: function (m) {
- var te = this.elements, tem = m.elements;
- te[0] += tem[0]; te[1] += tem[1]; te[2] += tem[2];
- te[3] += tem[3]; te[4] += tem[4]; te[5] += tem[5];
- te[6] += tem[6]; te[7] += tem[7]; te[8] += tem[8];
- return this;
- },
- sub: function (m1, m2) {
- var te = this.elements, tem1 = m1.elements, tem2 = m2.elements;
- te[0] = tem1[0] - tem2[0]; te[1] = tem1[1] - tem2[1]; te[2] = tem1[2] - tem2[2];
- te[3] = tem1[3] - tem2[3]; te[4] = tem1[4] - tem2[4]; te[5] = tem1[5] - tem2[5];
- te[6] = tem1[6] - tem2[6]; te[7] = tem1[7] - tem2[7]; te[8] = tem1[8] - tem2[8];
- return this;
- },
- subEqual: function (m) {
- var te = this.elements, tem = m.elements;
- te[0] -= tem[0]; te[1] -= tem[1]; te[2] -= tem[2];
- te[3] -= tem[3]; te[4] -= tem[4]; te[5] -= tem[5];
- te[6] -= tem[6]; te[7] -= tem[7]; te[8] -= tem[8];
- return this;
- },
- scale: function (m, s) {
- var te = this.elements, tm = m.elements;
- te[0] = tm[0] * s; te[1] = tm[1] * s; te[2] = tm[2] * s;
- te[3] = tm[3] * s; te[4] = tm[4] * s; te[5] = tm[5] * s;
- te[6] = tm[6] * s; te[7] = tm[7] * s; te[8] = tm[8] * s;
- return this;
- },
- scaleEqual: function (s) {
- var te = this.elements;
- te[0] *= s; te[1] *= s; te[2] *= s;
- te[3] *= s; te[4] *= s; te[5] *= s;
- te[6] *= s; te[7] *= s; te[8] *= s;
- return this;
- },
- mul: function (m1, m2) {
- var te = this.elements, tm1 = m1.elements, tm2 = m2.elements,
- a0 = tm1[0], a3 = tm1[3], a6 = tm1[6],
- a1 = tm1[1], a4 = tm1[4], a7 = tm1[7],
- a2 = tm1[2], a5 = tm1[5], a8 = tm1[8],
- b0 = tm2[0], b3 = tm2[3], b6 = tm2[6],
- b1 = tm2[1], b4 = tm2[4], b7 = tm2[7],
- b2 = tm2[2], b5 = tm2[5], b8 = tm2[8];
- te[0] = a0 * b0 + a1 * b3 + a2 * b6;
- te[1] = a0 * b1 + a1 * b4 + a2 * b7;
- te[2] = a0 * b2 + a1 * b5 + a2 * b8;
- te[3] = a3 * b0 + a4 * b3 + a5 * b6;
- te[4] = a3 * b1 + a4 * b4 + a5 * b7;
- te[5] = a3 * b2 + a4 * b5 + a5 * b8;
- te[6] = a6 * b0 + a7 * b3 + a8 * b6;
- te[7] = a6 * b1 + a7 * b4 + a8 * b7;
- te[8] = a6 * b2 + a7 * b5 + a8 * b8;
- return this;
- },
- mulScale: function (m, sx, sy, sz, Prepend) {
- var prepend = Prepend || false;
- var te = this.elements, tm = m.elements;
- if (prepend) {
- te[0] = sx * tm[0]; te[1] = sx * tm[1]; te[2] = sx * tm[2];
- te[3] = sy * tm[3]; te[4] = sy * tm[4]; te[5] = sy * tm[5];
- te[6] = sz * tm[6]; te[7] = sz * tm[7]; te[8] = sz * tm[8];
- } else {
- te[0] = tm[0] * sx; te[1] = tm[1] * sy; te[2] = tm[2] * sz;
- te[3] = tm[3] * sx; te[4] = tm[4] * sy; te[5] = tm[5] * sz;
- te[6] = tm[6] * sx; te[7] = tm[7] * sy; te[8] = tm[8] * sz;
- }
- return this;
- },
- mulRotate: function (m, rad, ax, ay, az, Prepend) {
- var prepend = Prepend || false;
- var s = OIMO.sin(rad);
- var c = OIMO.cos(rad);
- var c1 = 1 - c;
- var r00 = ax * ax * c1 + c;
- var r01 = ax * ay * c1 - az * s;
- var r02 = ax * az * c1 + ay * s;
- var r10 = ay * ax * c1 + az * s;
- var r11 = ay * ay * c1 + c;
- var r12 = ay * az * c1 - ax * s;
- var r20 = az * ax * c1 - ay * s;
- var r21 = az * ay * c1 + ax * s;
- var r22 = az * az * c1 + c;
- var tm = m.elements;
- var a0 = tm[0], a3 = tm[3], a6 = tm[6];
- var a1 = tm[1], a4 = tm[4], a7 = tm[7];
- var a2 = tm[2], a5 = tm[5], a8 = tm[8];
- var te = this.elements;
- if (prepend) {
- te[0] = r00 * a0 + r01 * a3 + r02 * a6;
- te[1] = r00 * a1 + r01 * a4 + r02 * a7;
- te[2] = r00 * a2 + r01 * a5 + r02 * a8;
- te[3] = r10 * a0 + r11 * a3 + r12 * a6;
- te[4] = r10 * a1 + r11 * a4 + r12 * a7;
- te[5] = r10 * a2 + r11 * a5 + r12 * a8;
- te[6] = r20 * a0 + r21 * a3 + r22 * a6;
- te[7] = r20 * a1 + r21 * a4 + r22 * a7;
- te[8] = r20 * a2 + r21 * a5 + r22 * a8;
- } else {
- te[0] = a0 * r00 + a1 * r10 + a2 * r20;
- te[1] = a0 * r01 + a1 * r11 + a2 * r21;
- te[2] = a0 * r02 + a1 * r12 + a2 * r22;
- te[3] = a3 * r00 + a4 * r10 + a5 * r20;
- te[4] = a3 * r01 + a4 * r11 + a5 * r21;
- te[5] = a3 * r02 + a4 * r12 + a5 * r22;
- te[6] = a6 * r00 + a7 * r10 + a8 * r20;
- te[7] = a6 * r01 + a7 * r11 + a8 * r21;
- te[8] = a6 * r02 + a7 * r12 + a8 * r22;
- }
- return this;
- },
- transpose: function (m) {
- var te = this.elements, tm = m.elements;
- te[0] = tm[0]; te[1] = tm[3]; te[2] = tm[6];
- te[3] = tm[1]; te[4] = tm[4]; te[5] = tm[7];
- te[6] = tm[2]; te[7] = tm[5]; te[8] = tm[8];
- return this;
- },
- setQuat: function (q) {
- var te = this.elements,
- x2 = 2 * q.x, y2 = 2 * q.y, z2 = 2 * q.z,
- xx = q.x * x2, yy = q.y * y2, zz = q.z * z2,
- xy = q.x * y2, yz = q.y * z2, xz = q.x * z2,
- sx = q.s * x2, sy = q.s * y2, sz = q.s * z2;
- te[0] = 1 - yy - zz;
- te[1] = xy - sz;
- te[2] = xz + sy;
- te[3] = xy + sz;
- te[4] = 1 - xx - zz;
- te[5] = yz - sx;
- te[6] = xz - sy;
- te[7] = yz + sx;
- te[8] = 1 - xx - yy;
- return this;
- },
- invert: function (m) {
- var te = this.elements, tm = m.elements,
- a0 = tm[0], a3 = tm[3], a6 = tm[6],
- a1 = tm[1], a4 = tm[4], a7 = tm[7],
- a2 = tm[2], a5 = tm[5], a8 = tm[8],
- b01 = a4 * a8 - a7 * a5,
- b11 = a7 * a2 - a1 * a8,
- b21 = a1 * a5 - a4 * a2,
- dt = a0 * (b01) + a3 * (b11) + a6 * (b21);
- if (dt != 0) { dt = 1.0 / dt; }
- te[0] = dt * b01;//(a4*a8 - a5*a7);
- te[1] = dt * b11;//(a2*a7 - a1*a8);
- te[2] = dt * b21;//(a1*a5 - a2*a4);
- te[3] = dt * (a5 * a6 - a3 * a8);
- te[4] = dt * (a0 * a8 - a2 * a6);
- te[5] = dt * (a2 * a3 - a0 * a5);
- te[6] = dt * (a3 * a7 - a4 * a6);
- te[7] = dt * (a1 * a6 - a0 * a7);
- te[8] = dt * (a0 * a4 - a1 * a3);
- return this;
- },
- /*copy: function(m){
- var te = this.elements, tem = m.elements;
- te[0] = tem[0]; te[1] = tem[1]; te[2] = tem[2];
- te[3] = tem[3]; te[4] = tem[4]; te[5] = tem[5];
- te[6] = tem[6]; te[7] = tem[7]; te[8] = tem[8];
- return this;
- },*/
- toEuler: function () { // not work !!
- function clamp(x) {
- return OIMO.min(OIMO.max(x, -1), 1);
- }
- var te = this.elements;
- var m11 = te[0], m12 = te[3], m13 = te[6];
- var m21 = te[1], m22 = te[4], m23 = te[7];
- var m31 = te[2], m32 = te[5], m33 = te[8];
- var p = new OIMO.Vec3();
- var d = new OIMO.Quat();
- var s;
- p.y = OIMO.asin(clamp(m13));
- if (OIMO.abs(m13) < 0.99999) {
- p.x = OIMO.atan2(-m23, m33);
- p.z = OIMO.atan2(-m12, m11);
- } else {
- p.x = OIMO.atan2(m32, m22);
- p.z = 0;
- }
- return p;
- },
- /*clone: function(){
- var te = this.elements;
- return new OIMO.Mat33(
- te[0], te[1], te[2],
- te[3], te[4], te[5],
- te[6], te[7], te[8]
- );
- },*/
- toString: function () {
- var te = this.elements;
- var text =
- "Mat33|" + te[0].toFixed(4) + ", " + te[1].toFixed(4) + ", " + te[2].toFixed(4) + "|\n" +
- " |" + te[3].toFixed(4) + ", " + te[4].toFixed(4) + ", " + te[5].toFixed(4) + "|\n" +
- " |" + te[6].toFixed(4) + ", " + te[7].toFixed(4) + ", " + te[8].toFixed(4) + "|";
- return text;
- },
- // OK
- multiplyScalar: function (s) {
- var te = this.elements;
- te[0] *= s; te[3] *= s; te[6] *= s;
- te[1] *= s; te[4] *= s; te[7] *= s;
- te[2] *= s; te[5] *= s; te[8] *= s;
- return this;
- },
- identity: function () {
- this.set(1, 0, 0, 0, 1, 0, 0, 0, 1);
- return this;
- },
- clone: function () {
- return new this.constructor().fromArray(this.elements);
- },
- copy: function (m) {
- var me = m.elements;
- this.set(
- me[0], me[3], me[6],
- me[1], me[4], me[7],
- me[2], me[5], me[8]
- );
- return this;
- },
- fromArray: function (array) {
- this.elements.set(array);
- return this;
- },
- toArray: function () {
- var te = this.elements;
- return [
- te[0], te[1], te[2],
- te[3], te[4], te[5],
- te[6], te[7], te[8]
- ];
- }
- };
- OIMO.Quat = function (s, x, y, z) {
- this.s = (s !== undefined) ? s : 1;
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- };
- OIMO.Quat.prototype = {
- constructor: OIMO.Quat,
- set: function (x, y, z, w) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.s = w;
- return this;
- },
- init: function (s, x, y, z) {
- this.s = (s !== undefined) ? s : 1;
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- return this;
- },
- add: function (q1, q2) {
- this.s = q1.s + q2.s;
- this.x = q1.x + q2.x;
- this.y = q1.y + q2.y;
- this.z = q1.z + q2.z;
- return this;
- },
- addTime: function (v, t) {
- var x = v.x;
- var y = v.y;
- var z = v.z;
- var qs = this.s;
- var qx = this.x;
- var qy = this.y;
- var qz = this.z;
- t *= 0.5;
- var ns = (-x * qx - y * qy - z * qz) * t;
- var nx = (x * qs + y * qz - z * qy) * t;
- var ny = (-x * qz + y * qs + z * qx) * t;
- var nz = (x * qy - y * qx + z * qs) * t;
- qs += ns;
- qx += nx;
- qy += ny;
- qz += nz;
- var s = 1 / OIMO.sqrt(qs * qs + qx * qx + qy * qy + qz * qz);
- this.s = qs * s;
- this.x = qx * s;
- this.y = qy * s;
- this.z = qz * s;
- return this;
- },
- sub: function (q1, q2) {
- this.s = q1.s - q2.s;
- this.x = q1.x - q2.x;
- this.y = q1.y - q2.y;
- this.z = q1.z - q2.z;
- return this;
- },
- scale: function (q, s) {
- this.s = q.s * s;
- this.x = q.x * s;
- this.y = q.y * s;
- this.z = q.z * s;
- return this;
- },
- mul: function (q1, q2) {
- var ax = q1.x, ay = q1.y, az = q1.z, as = q1.s,
- bx = q2.x, by = q2.y, bz = q2.z, bs = q2.s;
- this.x = ax * bs + as * bx + ay * bz - az * by;
- this.y = ay * bs + as * by + az * bx - ax * bz;
- this.z = az * bs + as * bz + ax * by - ay * bx;
- this.s = as * bs - ax * bx - ay * by - az * bz;
- return this;
- },
- arc: function (v1, v2) {
- var x1 = v1.x;
- var y1 = v1.y;
- var z1 = v1.z;
- var x2 = v2.x;
- var y2 = v2.y;
- var z2 = v2.z;
- var d = x1 * x2 + y1 * y2 + z1 * z2;
- if (d == -1) {
- x2 = y1 * x1 - z1 * z1;
- y2 = -z1 * y1 - x1 * x1;
- z2 = x1 * z1 + y1 * y1;
- d = 1 / OIMO.sqrt(x2 * x2 + y2 * y2 + z2 * z2);
- this.s = 0;
- this.x = x2 * d;
- this.y = y2 * d;
- this.z = z2 * d;
- return this;
- }
- var cx = y1 * z2 - z1 * y2;
- var cy = z1 * x2 - x1 * z2;
- var cz = x1 * y2 - y1 * x2;
- this.s = OIMO.sqrt((1 + d) * 0.5);
- d = 0.5 / this.s;
- this.x = cx * d;
- this.y = cy * d;
- this.z = cz * d;
- return this;
- },
- normalize: function (q) {
- var len = OIMO.sqrt(q.s * q.s + q.x * q.x + q.y * q.y + q.z * q.z);
- if (len > 0) { len = 1 / len; }
- this.s = q.s * len;
- this.x = q.x * len;
- this.y = q.y * len;
- this.z = q.z * len;
- return this;
- },
- invert: function (q) {
- this.s = q.s;
- this.x = -q.x;
- this.y = -q.y;
- this.z = -q.z;
- return this;
- },
- length: function () {
- return OIMO.sqrt(this.s * this.s + this.x * this.x + this.y * this.y + this.z * this.z);
- },
- copy: function (q) {
- this.s = q.s;
- this.x = q.x;
- this.y = q.y;
- this.z = q.z;
- return this;
- },
- testDiff: function (q) {
- if (this.s !== q.s || this.x !== q.x || this.y !== q.y || this.z !== q.z) return true;
- else return false;
- },
- clone: function (q) {
- return new OIMO.Quat(this.s, this.x, this.y, this.z);
- },
- toString: function () {
- return "Quat[" + this.s.toFixed(4) + ", (" + this.x.toFixed(4) + ", " + this.y.toFixed(4) + ", " + this.z.toFixed(4) + ")]";
- }
- }
- // for three easy export
- OIMO.Quaternion = function (x, y, z, w) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- this.w = (w !== undefined) ? w : 1;
- };
- OIMO.Quaternion.prototype = {
- constructor: OIMO.Quaternion,
- setFromRotationMatrix: function (m) {
- // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- var te = m.elements,
- m11 = te[0], m12 = te[1], m13 = te[2],
- m21 = te[3], m22 = te[4], m23 = te[5],
- m31 = te[6], m32 = te[7], m33 = te[8],
- trace = m11 + m22 + m33,
- s;
- if (trace > 0) {
- s = 0.5 / OIMO.sqrt(trace + 1.0);
- this.w = 0.25 / s;
- this.x = (m32 - m23) * s;
- this.y = (m13 - m31) * s;
- this.z = (m21 - m12) * s;
- } else if (m11 > m22 && m11 > m33) {
- s = 2.0 * OIMO.sqrt(1.0 + m11 - m22 - m33);
- this.w = (m32 - m23) / s;
- this.x = 0.25 * s;
- this.y = (m12 + m21) / s;
- this.z = (m13 + m31) / s;
- } else if (m22 > m33) {
- s = 2.0 * OIMO.sqrt(1.0 + m22 - m11 - m33);
- this.w = (m13 - m31) / s;
- this.x = (m12 + m21) / s;
- this.y = 0.25 * s;
- this.z = (m23 + m32) / s;
- } else {
- s = 2.0 * OIMO.sqrt(1.0 + m33 - m11 - m22);
- this.w = (m21 - m12) / s;
- this.x = (m13 + m31) / s;
- this.y = (m23 + m32) / s;
- this.z = 0.25 * s;
- }
- //this.onChangeCallback();
- return this;
- }
- }
- OIMO.Vec3 = function (x, y, z) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- };
- OIMO.Vec3.prototype = {
- constructor: OIMO.Vec3,
- init: function (x, y, z) {
- this.x = x || 0;
- this.y = y || 0;
- this.z = z || 0;
- return this;
- },
- set: function (x, y, z) {
- this.x = x;
- this.y = y;
- this.z = z;
- return this;
- },
- add: function (v1, v2) {
- this.x = v1.x + v2.x;
- this.y = v1.y + v2.y;
- this.z = v1.z + v2.z;
- return this;
- },
- addEqual: function (v) {
- this.x += v.x;
- this.y += v.y;
- this.z += v.z;
- return this;
- },
- addTime: function (v, t) {
- this.x += v.x * t;
- this.y += v.y * t;
- this.z += v.z * t;
- return this;
- },
- sub: function (v1, v2) {
- this.x = v1.x - v2.x;
- this.y = v1.y - v2.y;
- this.z = v1.z - v2.z;
- return this;
- },
- subEqual: function (v) {
- this.x -= v.x;
- this.y -= v.y;
- this.z -= v.z;
- return this;
- },
- addScale: function (v, s) {
- this.x += v.x * s;
- this.y += v.y * s;
- this.z += v.z * s;
- return this;
- },
- scale: function (v, s) {
- this.x = v.x * s;
- this.y = v.y * s;
- this.z = v.z * s;
- return this;
- },
- scaleEqual: function (s) {
- this.x *= s;
- this.y *= s;
- this.z *= s;
- return this;
- },
- /*dot: function(v){
- return this.x*v.x+this.y*v.y+this.z*v.z;
- },*/
- cross: function (v1, v2) {
- var ax = v1.x, ay = v1.y, az = v1.z,
- bx = v2.x, by = v2.y, bz = v2.z;
- this.x = ay * bz - az * by;
- this.y = az * bx - ax * bz;
- this.z = ax * by - ay * bx;
- return this;
- },
- mul: function (o, v, m) {
- var te = m.elements;
- this.x = o.x + v.x * te[0] + v.y * te[1] + v.z * te[2];
- this.y = o.y + v.x * te[3] + v.y * te[4] + v.z * te[5];
- this.z = o.z + v.x * te[6] + v.y * te[7] + v.z * te[8];
- return this;
- },
- mulMat: function (m, v) {
- var te = m.elements;
- this.x = te[0] * v.x + te[1] * v.y + te[2] * v.z;
- this.y = te[3] * v.x + te[4] * v.y + te[5] * v.z;
- this.z = te[6] * v.x + te[7] * v.y + te[8] * v.z;
- return this;
- },
- normalize: function (v) {
- var x = v.x, y = v.y, z = v.z;
- var l = x * x + y * y + z * z;
- if (l > 0) {
- l = 1 / OIMO.sqrt(l);
- this.x = x * l;
- this.y = y * l;
- this.z = z * l;
- }
- return this;
- },
- /*norm: function(){
- var x = this.x, y = this.y, z = this.z;
- var l = x*x + y*y + z*z;
- if (l > 0) {
- l = 1 / OIMO.sqrt(l);
- this.x = x*l;
- this.y = y*l;
- this.z = z*l;
- }
- return this;
- },*/
- invert: function (v) {
- this.x = -v.x;
- this.y = -v.y;
- this.z = -v.z;
- return this;
- },
- /*length: function(){
- var x = this.x, y = this.y, z = this.z;
- return OIMO.sqrt(x*x + y*y + z*z);
- },*/
- negate: function () {
- this.x = -this.x;
- this.y = -this.y;
- this.z = -this.z;
- return this;
- },
- dot: function (v) {
- return this.x * v.x + this.y * v.y + this.z * v.z;
- },
- lengthSq: function () {
- return this.x * this.x + this.y * this.y + this.z * this.z;
- },
- length: function () {
- return OIMO.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
- },
- /*len: function(){
- var x = this.x, y = this.y, z = this.z;
- return x*x + y*y + z*z;
- },*/
- copy: function (v) {
- this.x = v.x;
- this.y = v.y;
- this.z = v.z;
- return this;
- },
- applyQuaternion: function (q) {
- var x = this.x;
- var y = this.y;
- var z = this.z;
- var qx = q.x;
- var qy = q.y;
- var qz = q.z;
- var qs = q.s;
- // calculate quat * vector
- var ix = qs * x + qy * z - qz * y;
- var iy = qs * y + qz * x - qx * z;
- var iz = qs * z + qx * y - qy * x;
- var iw = -qx * x - qy * y - qz * z;
- // calculate result * inverse quat
- this.x = ix * qs + iw * -qx + iy * -qz - iz * -qy;
- this.y = iy * qs + iw * -qy + iz * -qx - ix * -qz;
- this.z = iz * qs + iw * -qz + ix * -qy - iy * -qx;
- return this;
- },
- testZero: function () {
- if (this.x !== 0 || this.y !== 0 || this.z !== 0) return true;
- else return false;
- },
- testDiff: function (v) {
- return ((v.x !== this.x) || (v.y !== this.y) || (v.z !== this.z));
- //if(this.x!==v.x || this.y!==v.y || this.z!==v.z) return true;
- //else return false;
- },
- equals: function (v) {
- return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
- },
- clone: function () {
- return new this.constructor(this.x, this.y, this.z);
- },
- toString: function () {
- return "Vec3[" + this.x.toFixed(4) + ", " + this.y.toFixed(4) + ", " + this.z.toFixed(4) + "]";
- },
- multiplyScalar: function (scalar) {
- if (isFinite(scalar)) {
- this.x *= scalar;
- this.y *= scalar;
- this.z *= scalar;
- } else {
- this.x = 0;
- this.y = 0;
- this.z = 0;
- }
- return this;
- },
- divideScalar: function (scalar) {
- return this.multiplyScalar(1 / scalar);
- },
- // TODO rename to normalize
- norm: function () {
- return this.divideScalar(this.length());
- },
- }
- OIMO.Euler = function (x, y, z, order) {
- this._x = x || 0;
- this._y = y || 0;
- this._z = z || 0;
- this._order = order || OIMO.Euler.DefaultOrder;
- };
- OIMO.Euler.RotationOrders = ['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX'];
- OIMO.Euler.DefaultOrder = 'XYZ';
- OIMO.clamp = function (x, a, b) {
- return (x < a) ? a : ((x > b) ? b : x);
- }
- OIMO.Euler.prototype = {
- constructor: OIMO.Euler,
- _x: 0, _y: 0, _z: 0, _order: OIMO.Euler.DefaultOrder,
- get x() {
- return this._x;
- },
- set x(value) {
- this._x = value;
- this.onChangeCallback();
- },
- get y() {
- return this._y;
- },
- set y(value) {
- this._y = value;
- this.onChangeCallback();
- },
- get z() {
- return this._z;
- },
- set z(value) {
- this._z = value;
- this.onChangeCallback();
- },
- get order() {
- return this._order;
- },
- set order(value) {
- this._order = value;
- this.onChangeCallback();
- },
- set: function (x, y, z, order) {
- this._x = x;
- this._y = y;
- this._z = z;
- this._order = order || this._order;
- this.onChangeCallback();
- return this;
- },
- copy: function (euler) {
- this._x = euler._x;
- this._y = euler._y;
- this._z = euler._z;
- this._order = euler._order;
- this.onChangeCallback();
- return this;
- },
- setFromRotationMatrix: function (m, order) {
- var clamp = OIMO.clamp;
- // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
- var te = m.elements;
- /*var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
- var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
- var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];*/
- var m11 = te[0], m12 = te[1], m13 = te[2],
- m21 = te[3], m22 = te[4], m23 = te[5],
- m31 = te[6], m32 = te[7], m33 = te[8];
- order = order || this._order;
- if (order === 'XYZ') {
- this._y = OIMO.asin(clamp(m13, -1, 1));
- if (OIMO.abs(m13) < 0.99999) {
- this._x = OIMO.atan2(-m23, m33);
- this._z = OIMO.atan2(-m12, m11);
- } else {
- this._x = OIMO.atan2(m32, m22);
- this._z = 0;
- }
- } else if (order === 'YXZ') {
- this._x = OIMO.asin(-clamp(m23, -1, 1));
- if (OIMO.abs(m23) < 0.99999) {
- this._y = OIMO.atan2(m13, m33);
- this._z = OIMO.atan2(m21, m22);
- } else {
- this._y = OIMO.atan2(-m31, m11);
- this._z = 0;
- }
- } else if (order === 'ZXY') {
- this._x = OIMO.asin(clamp(m32, -1, 1));
- if (OIMO.abs(m32) < 0.99999) {
- this._y = OIMO.atan2(-m31, m33);
- this._z = OIMO.atan2(-m12, m22);
- } else {
- this._y = 0;
- this._z = OIMO.atan2(m21, m11);
- }
- } else if (order === 'ZYX') {
- this._y = OIMO.asin(-clamp(m31, -1, 1));
- if (OIMO.abs(m31) < 0.99999) {
- this._x = OIMO.atan2(m32, m33);
- this._z = OIMO.atan2(m21, m11);
- } else {
- this._x = 0;
- this._z = OIMO.atan2(-m12, m22);
- }
- } else if (order === 'YZX') {
- this._z = OIMO.asin(clamp(m21, -1, 1));
- if (OIMO.abs(m21) < 0.99999) {
- this._x = OIMO.atan2(-m23, m22);
- this._y = OIMO.atan2(-m31, m11);
- } else {
- this._x = 0;
- this._y = OIMO.atan2(m13, m33);
- }
- } else if (order === 'XZY') {
- this._z = OIMO.asin(-clamp(m12, -1, 1));
- if (OIMO.abs(m12) < 0.99999) {
- this._x = OIMO.atan2(m32, m22);
- this._y = OIMO.atan2(m13, m11);
- } else {
- this._x = OIMO.atan2(-m23, m33);
- this._y = 0;
- }
- } else {
- console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order)
- }
- this._order = order;
- this.onChangeCallback();
- return this;
- },
- setFromQuaternion: function (q, order, update) {
- var clamp = OIMO.clamp;
- // q is assumed to be normalized
- // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
- var sqx = q.x * q.x;
- var sqy = q.y * q.y;
- var sqz = q.z * q.z;
- var sqw = q.s * q.s;
- order = order || this._order;
- if (order === 'XYZ') {
- this._x = OIMO.atan2(2 * (q.x * q.s - q.y * q.z), (sqw - sqx - sqy + sqz));
- this._y = OIMO.asin(clamp(2 * (q.x * q.z + q.y * q.s), -1, 1));
- this._z = OIMO.atan2(2 * (q.z * q.s - q.x * q.y), (sqw + sqx - sqy - sqz));
- } else if (order === 'YXZ') {
- this._x = OIMO.asin(clamp(2 * (q.x * q.s - q.y * q.z), -1, 1));
- this._y = OIMO.atan2(2 * (q.x * q.z + q.y * q.s), (sqw - sqx - sqy + sqz));
- this._z = OIMO.atan2(2 * (q.x * q.y + q.z * q.s), (sqw - sqx + sqy - sqz));
- } else if (order === 'ZXY') {
- this._x = OIMO.asin(clamp(2 * (q.x * q.s + q.y * q.z), -1, 1));
- this._y = OIMO.atan2(2 * (q.y * q.s - q.z * q.x), (sqw - sqx - sqy + sqz));
- this._z = OIMO.atan2(2 * (q.z * q.s - q.x * q.y), (sqw - sqx + sqy - sqz));
- } else if (order === 'ZYX') {
- this._x = OIMO.atan2(2 * (q.x * q.s + q.z * q.y), (sqw - sqx - sqy + sqz));
- this._y = OIMO.asin(clamp(2 * (q.y * q.s - q.x * q.z), -1, 1));
- this._z = OIMO.atan2(2 * (q.x * q.y + q.z * q.s), (sqw + sqx - sqy - sqz));
- } else if (order === 'YZX') {
- this._x = OIMO.atan2(2 * (q.x * q.s - q.z * q.y), (sqw - sqx + sqy - sqz));
- this._y = OIMO.atan2(2 * (q.y * q.s - q.x * q.z), (sqw + sqx - sqy - sqz));
- this._z = OIMO.asin(clamp(2 * (q.x * q.y + q.z * q.s), -1, 1));
- } else if (order === 'XZY') {
- this._x = OIMO.atan2(2 * (q.x * q.s + q.y * q.z), (sqw - sqx + sqy - sqz));
- this._y = OIMO.atan2(2 * (q.x * q.z + q.y * q.s), (sqw + sqx - sqy - sqz));
- this._z = OIMO.asin(clamp(2 * (q.z * q.s - q.x * q.y), -1, 1));
- } else {
- console.warn('OIMO.Euler: .setFromQuaternion() given unsupported order: ' + order)
- }
- this._order = order;
- if (update !== false) this.onChangeCallback();
- return this;
- },
- reorder: function () {
- // WARNING: this discards revolution information -bhouston
- var q = new OIMO.Quat();
- return function (newOrder) {
- q.setFromEuler(this);
- this.setFromQuaternion(q, newOrder);
- };
- }(),
- equals: function (euler) {
- return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
- },
- fromArray: function (array) {
- this._x = array[0];
- this._y = array[1];
- this._z = array[2];
- if (array[3] !== undefined) this._order = array[3];
- this.onChangeCallback();
- return this;
- },
- toArray: function () {
- return [this._x, this._y, this._z, this._order];
- },
- onChange: function (callback) {
- this.onChangeCallback = callback;
- return this;
- },
- onChangeCallback: function () { },
- clone: function () {
- return new OIMO.Euler(this._x, this._y, this._z, this._order);
- }
- };
- OIMO.EulerToAxis = function (ox, oy, oz) {// angles in radians
- var c1 = OIMO.cos(oy * 0.5);//heading
- var s1 = OIMO.sin(oy * 0.5);
- var c2 = OIMO.cos(oz * 0.5);//altitude
- var s2 = OIMO.sin(oz * 0.5);
- var c3 = OIMO.cos(ox * 0.5);//bank
- var s3 = OIMO.sin(ox * 0.5);
- var c1c2 = c1 * c2;
- var s1s2 = s1 * s2;
- var w = c1c2 * c3 - s1s2 * s3;
- var x = c1c2 * s3 + s1s2 * c3;
- var y = s1 * c2 * c3 + c1 * s2 * s3;
- var z = c1 * s2 * c3 - s1 * c2 * s3;
- var angle = 2 * OIMO.acos(w);
- var norm = x * x + y * y + z * z;
- if (norm < 0.001) {
- x = 1;
- y = z = 0;
- } else {
- norm = OIMO.sqrt(norm);
- x /= norm;
- y /= norm;
- z /= norm;
- }
- return [angle, x, y, z];
- }
- OIMO.EulerToMatrix = function (ox, oy, oz) {// angles in radians
- var ch = OIMO.cos(oy);//heading
- var sh = OIMO.sin(oy);
- var ca = OIMO.cos(oz);//altitude
- var sa = OIMO.sin(oz);
- var cb = OIMO.cos(ox);//bank
- var sb = OIMO.sin(ox);
- var mtx = new OIMO.Mat33();
- var te = mtx.elements;
- te[0] = ch * ca;
- te[1] = sh * sb - ch * sa * cb;
- te[2] = ch * sa * sb + sh * cb;
- te[3] = sa;
- te[4] = ca * cb;
- te[5] = -ca * sb;
- te[6] = -sh * ca;
- te[7] = sh * sa * cb + ch * sb;
- te[8] = -sh * sa * sb + ch * cb;
- return mtx;
- }
- OIMO.MatrixToEuler = function (mtx) {// angles in radians
- var te = mtx.elements;
- var x, y, z;
- if (te[3] > 0.998) { // singularity at north pole
- y = OIMO.atan2(te[2], te[8]);
- z = OIMO.PI / 2;
- x = 0;
- } else if (te[3] < -0.998) { // singularity at south pole
- y = OIMO.atan2(te[2], te[8]);
- z = -OIMO.PI / 2;
- x = 0;
- } else {
- y = OIMO.atan2(-te[6], te[0]);
- x = OIMO.atan2(-te[5], te[4]);
- z = OIMO.asin(te[3]);
- }
- return [x, y, z];
- }
- OIMO.unwrapDegrees = function (r) {
- r = r % 360;
- if (r > 180) r -= 360;
- if (r < -180) r += 360;
- return r;
- }
- OIMO.unwrapRadian = function (r) {
- r = r % OIMO.TwoPI;
- if (r > OIMO.PI) r -= OIMO.TwoPI;
- if (r < -OIMO.PI) r += OIMO.TwoPI;
- return r;
- }
- OIMO.Distance3d = function (p1, p2) {
- var xd = p2[0] - p1[0];
- var yd = p2[1] - p1[1];
- var zd = p2[2] - p1[2];
- return OIMO.sqrt(xd * xd + yd * yd + zd * zd);
- }
- /**
- * The base class of all type of the constraints.
- * @author saharan
- */
- OIMO.Constraint = function () {
- // The parent world of the constraint.
- this.parent = null;
- // The first body of the constraint.
- this.body1 = null;
- // The second body of the constraint.
- this.body2 = null;
- // Internal
- this.addedToIsland = false;
- }
- OIMO.Constraint.prototype = {
- constructor: OIMO.Constraint,
- /**
- * Prepare for solving the constraint.
- * @param timeStep
- * @param invTimeStep
- */
- preSolve: function (timeStep, invTimeStep) {
- OIMO.Error("Constraint", "Inheritance error.");
- },
- /**
- * Solve the constraint.
- * This is usually called iteratively.
- */
- solve: function () {
- OIMO.Error("Constraint", "Inheritance error.");
- },
- /**
- * Do the post-processing.
- */
- postSolve: function () {
- OIMO.Error("Constraint", "Inheritance error.");
- }
- }
- /**
- * Joints are used to constrain the motion between two rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.Joint = function (config) {
- OIMO.Constraint.call(this);
- // joint name
- this.name = "";
- // The type of the joint.
- this.type = OIMO.JOINT_NULL;
- // The previous joint in the world.
- this.prev = null;
- // The next joint in the world.
- this.next = null;
- this.body1 = config.body1;
- this.body2 = config.body2;
- // The anchor point on the first rigid body in local coordinate system.
- this.localAnchorPoint1 = new OIMO.Vec3().copy(config.localAnchorPoint1);
- // The anchor point on the second rigid body in local coordinate system.
- this.localAnchorPoint2 = new OIMO.Vec3().copy(config.localAnchorPoint2);
- // The anchor point on the first rigid body in world coordinate system relative to the body's origin.
- this.relativeAnchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in world coordinate system relative to the body's origin.
- this.relativeAnchorPoint2 = new OIMO.Vec3();
- // The anchor point on the first rigid body in world coordinate system.
- this.anchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in world coordinate system.
- this.anchorPoint2 = new OIMO.Vec3();
- // Whether allow collision between connected rigid bodies or not.
- this.allowCollision = config.allowCollision;
- this.b1Link = new OIMO.JointLink(this);
- this.b2Link = new OIMO.JointLink(this);
- this.matrix = new OIMO.Mat44();
- };
- OIMO.Joint.prototype = Object.create(OIMO.Constraint.prototype);
- OIMO.Joint.prototype.constructor = OIMO.Joint;
- // Update all the anchor points.
- OIMO.Joint.prototype.updateAnchorPoints = function () {
- this.relativeAnchorPoint1.mulMat(this.body1.rotation, this.localAnchorPoint1);
- this.relativeAnchorPoint2.mulMat(this.body2.rotation, this.localAnchorPoint2);
- this.anchorPoint1.add(this.relativeAnchorPoint1, this.body1.position);
- this.anchorPoint2.add(this.relativeAnchorPoint2, this.body2.position);
- };
- // Attach the joint from the bodies.
- OIMO.Joint.prototype.attach = function () {
- this.b1Link.body = this.body2;
- this.b2Link.body = this.body1;
- if (this.body1.jointLink != null) (this.b1Link.next = this.body1.jointLink).prev = this.b1Link;
- else this.b1Link.next = null;
- this.body1.jointLink = this.b1Link;
- this.body1.numJoints++;
- if (this.body2.jointLink != null) (this.b2Link.next = this.body2.jointLink).prev = this.b2Link;
- else this.b2Link.next = null;
- this.body2.jointLink = this.b2Link;
- this.body2.numJoints++;
- };
- // Detach the joint from the bodies.
- OIMO.Joint.prototype.detach = function () {
- var prev = this.b1Link.prev;
- var next = this.b1Link.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.body1.jointLink == this.b1Link) this.body1.jointLink = next;
- this.b1Link.prev = null;
- this.b1Link.next = null;
- this.b1Link.body = null;
- this.body1.numJoints--;
- prev = this.b2Link.prev;
- next = this.b2Link.next;
- if (prev != null) prev.next = next;
- if (next != null) next.prev = prev;
- if (this.body2.jointLink == this.b2Link) this.body2.jointLink = next;
- this.b2Link.prev = null;
- this.b2Link.next = null;
- this.b2Link.body = null;
- this.body2.numJoints--;
- this.b1Link.body = null;
- this.b2Link.body = null;
- };
- // Awake the bodies.
- OIMO.Joint.prototype.awake = function () {
- this.body1.awake();
- this.body2.awake();
- };
- // calculation function
- OIMO.Joint.prototype.preSolve = function (timeStep, invTimeStep) {
- };
- OIMO.Joint.prototype.solve = function () {
- };
- OIMO.Joint.prototype.postSolve = function () {
- };
- // Delete process
- OIMO.Joint.prototype.remove = function () {
- this.dispose();
- };
- OIMO.Joint.prototype.dispose = function () {
- this.parent.removeJoint(this);
- };
- // Three js add
- OIMO.Joint.prototype.getPosition = function () {
- var p1 = new OIMO.Vec3().scale(this.anchorPoint1, OIMO.WORLD_SCALE);
- var p2 = new OIMO.Vec3().scale(this.anchorPoint2, OIMO.WORLD_SCALE);
- return [p1, p2];
- };
- OIMO.Joint.prototype.getMatrix = function () {
- var m = this.matrix.elements;
- var p1 = this.anchorPoint1;
- var p2 = this.anchorPoint2;
- m[0] = p1.x * OIMO.WORLD_SCALE;
- m[1] = p1.y * OIMO.WORLD_SCALE;
- m[2] = p1.z * OIMO.WORLD_SCALE;
- m[3] = 0;
- m[4] = p2.x * OIMO.WORLD_SCALE;
- m[5] = p2.y * OIMO.WORLD_SCALE;
- m[6] = p2.z * OIMO.WORLD_SCALE;
- m[7] = 0;
- return m;
- };
- /**
- * A joint configuration holds all configuration data for constructing a joint.
- * Joint configurations can be reused safely.
- * @author saharan
- */
- OIMO.JointConfig = function () {
- // The first rigid body of the joint.
- this.body1 = null;
- // The second rigid body of the joint.
- this.body2 = null;
- // The anchor point on the first rigid body in local coordinate system.
- this.localAnchorPoint1 = new OIMO.Vec3();
- // The anchor point on the second rigid body in local coordinate system.
- this.localAnchorPoint2 = new OIMO.Vec3();
- // The axis in the first body's coordinate system.
- // his property is available in some joints.
- this.localAxis1 = new OIMO.Vec3();
- // The axis in the second body's coordinate system.
- // This property is available in some joints.
- this.localAxis2 = new OIMO.Vec3();
- // Whether allow collision between connected rigid bodies or not.
- this.allowCollision = false;
- };
- /**
- * A link list of joints.
- * @author saharan
- */
- OIMO.JointLink = function (joint) {
- // The previous joint link.
- this.prev = null;
- // The next joint link.
- this.next = null;
- // The other rigid body connected to the joint.
- this.body = null;
- // The joint of the link.
- this.joint = joint;
- };
- /**
- * An information of limit and motor.
- * @author saharan
- */
- OIMO.LimitMotor = function (axis, fixed) {
- fixed = fixed || false;
- // The axis of the constraint.
- this.axis = axis;
- // The current angle for rotational constraints.
- this.angle = 0;
- // The lower limit. Set lower > upper to disable
- this.lowerLimit = fixed ? 0 : 1;
- //if(fixed)this.lowerLimit = 0;
- //else this.lowerLimit = 1;
- // The upper limit. Set lower > upper to disable.
- this.upperLimit = 0;
- // The target motor speed.
- this.motorSpeed = 0;
- // The maximum motor force or torque. Set 0 to disable.
- this.maxMotorForce = 0;
- // The frequency of the spring. Set 0 to disable.
- this.frequency = 0;
- // The damping ratio of the spring. Set 0 for no damping, 1 for critical damping.
- this.dampingRatio = 0;
- };
- OIMO.LimitMotor.prototype = {
- constructor: OIMO.LimitMotor,
- /**
- * Set limit data into this constraint.
- * @param lowerLimit
- * @param upperLimit
- */
- setLimit: function (lowerLimit, upperLimit) {
- this.lowerLimit = lowerLimit;
- this.upperLimit = upperLimit;
- },
- /**
- * Set motor data into this constraint.
- * @param motorSpeed
- * @param maxMotorForce
- */
- setMotor: function (motorSpeed, maxMotorForce) {
- this.motorSpeed = motorSpeed;
- this.maxMotorForce = maxMotorForce;
- },
- /**
- * Set spring data into this constraint.
- * @param frequency
- * @param dampingRatio
- */
- setSpring: function (frequency, dampingRatio) {
- this.frequency = frequency;
- this.dampingRatio = dampingRatio;
- }
- };
- /**
- * A ball-and-socket joint limits relative translation on two anchor points on rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.BallAndSocketJoint = function (config) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_BALL_AND_SOCKET;
- this.lc = new OIMO.LinearConstraint(this);
- };
- OIMO.BallAndSocketJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.BallAndSocketJoint.prototype.constructor = OIMO.BallAndSocketJoint;
- OIMO.BallAndSocketJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.updateAnchorPoints();
- this.lc.preSolve(timeStep, invTimeStep);
- };
- OIMO.BallAndSocketJoint.prototype.solve = function () {
- this.lc.solve();
- };
- OIMO.BallAndSocketJoint.prototype.postSolve = function () {
- };
- /**
- * A distance joint limits the distance between two anchor points on rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.DistanceJoint = function (config, minDistance, maxDistance) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_DISTANCE;
- this.normal = new OIMO.Vec3();
- this.nr = new OIMO.Vec3();
- // The limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.normal, true);
- this.limitMotor.lowerLimit = minDistance;
- this.limitMotor.upperLimit = maxDistance;
- this.t = new OIMO.TranslationalConstraint(this, this.limitMotor);
- };
- OIMO.DistanceJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.DistanceJoint.prototype.constructor = OIMO.DistanceJoint;
- OIMO.DistanceJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.updateAnchorPoints();
- //var nr = this.nr;
- this.nr.sub(this.anchorPoint2, this.anchorPoint1);
- //var len = OIMO.sqrt( nr.x*nr.x + nr.y*nr.y + nr.z*nr.z );
- //if(len>0) len = 1/len;
- //this.normal.scale( nr, len );
- this.normal.normalize(this.nr);
- this.t.preSolve(timeStep, invTimeStep);
- };
- OIMO.DistanceJoint.prototype.solve = function () {
- this.t.solve();
- };
- OIMO.DistanceJoint.prototype.postSolve = function () {
- };
- /**
- * A hinge joint allows only for relative rotation of rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.HingeJoint = function (config, lowerAngleLimit, upperAngleLimit) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_HINGE;
- // The axis in the first body's coordinate system.
- this.localAxis1 = config.localAxis1.clone().norm();
- // The axis in the second body's coordinate system.
- this.localAxis2 = config.localAxis2.clone().norm();
- // make angle axis 1
- this.localAngle1 = new OIMO.Vec3(
- this.localAxis1.y * this.localAxis1.x - this.localAxis1.z * this.localAxis1.z,
- -this.localAxis1.z * this.localAxis1.y - this.localAxis1.x * this.localAxis1.x,
- this.localAxis1.x * this.localAxis1.z + this.localAxis1.y * this.localAxis1.y
- ).norm();
- // make angle axis 2
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- this.localAngle2 = new OIMO.Vec3().mulMat(arc, this.localAngle1);
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- this.ax1 = new OIMO.Vec3();
- this.ax2 = new OIMO.Vec3();
- this.an1 = new OIMO.Vec3();
- this.an2 = new OIMO.Vec3();
- // The rotational limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.nor, false);
- this.limitMotor.lowerLimit = lowerAngleLimit;
- this.limitMotor.upperLimit = upperAngleLimit;
- this.lc = new OIMO.LinearConstraint(this);
- this.r3 = new OIMO.Rotational3Constraint(this, this.limitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.HingeJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.HingeJoint.prototype.constructor = OIMO.HingeJoint;
- OIMO.HingeJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmp1X, tmp1Y, tmp1Z, limite;//, nx, ny, nz, tx, ty, tz, bx, by, bz;
- this.updateAnchorPoints();
- this.ax1.mulMat(this.body1.rotation, this.localAxis1);
- this.ax2.mulMat(this.body2.rotation, this.localAxis2);
- this.an1.mulMat(this.body1.rotation, this.localAngle1);
- this.an2.mulMat(this.body2.rotation, this.localAngle2);
- this.nor.set(
- this.ax1.x * this.body2.inverseMass + this.ax2.x * this.body1.inverseMass,
- this.ax1.y * this.body2.inverseMass + this.ax2.y * this.body1.inverseMass,
- this.ax1.z * this.body2.inverseMass + this.ax2.z * this.body1.inverseMass
- ).norm();
- this.tan.set(
- this.nor.y * this.nor.x - this.nor.z * this.nor.z,
- -this.nor.z * this.nor.y - this.nor.x * this.nor.x,
- this.nor.x * this.nor.z + this.nor.y * this.nor.y
- ).norm();
- this.bin.set(
- this.nor.y * this.tan.z - this.nor.z * this.tan.y,
- this.nor.z * this.tan.x - this.nor.x * this.tan.z,
- this.nor.x * this.tan.y - this.nor.y * this.tan.x
- );
- // calculate hinge angle
- limite = this.acosClamp(this.an1.x * this.an2.x + this.an1.y * this.an2.y + this.an1.z * this.an2.z)
- if (
- this.nor.x * (this.an1.y * this.an2.z - this.an1.z * this.an2.y) +
- this.nor.y * (this.an1.z * this.an2.x - this.an1.x * this.an2.z) +
- this.nor.z * (this.an1.x * this.an2.y - this.an1.y * this.an2.x) < 0
- ) {
- this.limitMotor.angle = -limite;
- } else {
- this.limitMotor.angle = limite;
- }
- tmp1X = this.ax1.y * this.ax2.z - this.ax1.z * this.ax2.y;
- tmp1Y = this.ax1.z * this.ax2.x - this.ax1.x * this.ax2.z;
- tmp1Z = this.ax1.x * this.ax2.y - this.ax1.y * this.ax2.x;
- this.r3.limitMotor2.angle = this.tan.x * tmp1X + this.tan.y * tmp1Y + this.tan.z * tmp1Z;
- this.r3.limitMotor3.angle = this.bin.x * tmp1X + this.bin.y * tmp1Y + this.bin.z * tmp1Z;
- this.r3.preSolve(timeStep, invTimeStep);
- this.lc.preSolve(timeStep, invTimeStep);
- };
- OIMO.HingeJoint.prototype.solve = function () {
- this.r3.solve();
- this.lc.solve();
- };
- OIMO.HingeJoint.prototype.postSolve = function () {
- };
- OIMO.HingeJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * A prismatic joint allows only for relative translation of rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.PrismaticJoint = function (config, lowerTranslation, upperTranslation) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_PRISMATIC;
- // The axis in the first body's coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The axis in the second body's coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- this.ac = new OIMO.AngularConstraint(this, new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- // The translational limit and motor information of the joint.
- this.limitMotor = new OIMO.LimitMotor(this.nor, true);
- this.limitMotor.lowerLimit = lowerTranslation;
- this.limitMotor.upperLimit = upperTranslation;
- this.t3 = new OIMO.Translational3Constraint(this, this.limitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.PrismaticJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.PrismaticJoint.prototype.constructor = OIMO.PrismaticJoint;
- OIMO.PrismaticJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var axis1X = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var axis1Y = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var axis1Z = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var axis2X = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var axis2Y = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var axis2Z = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var nx = axis1X * this.body2.inverseMass + axis2X * this.body1.inverseMass;
- var ny = axis1Y * this.body2.inverseMass + axis2Y * this.body1.inverseMass;
- var nz = axis1Z * this.body2.inverseMass + axis2Z * this.body1.inverseMass;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * nx - nz * nz;
- var ty = -nz * ny - nx * nx;
- var tz = nx * nz + ny * ny;
- tmp1X = 1 / OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = ny * tz - nz * ty;
- var by = nz * tx - nx * tz;
- var bz = nx * ty - ny * tx;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- this.ac.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.PrismaticJoint.prototype.solve = function () {
- this.ac.solve();
- this.t3.solve();
- };
- OIMO.PrismaticJoint.prototype.postSolve = function () {
- };
- /**
- * A slider joint allows for relative translation and relative rotation between two rigid bodies along the axis.
- * @author saharan
- * @author lo-th
- */
- OIMO.SliderJoint = function (config, lowerTranslation, upperTranslation) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_SLIDER;
- // The first axis in local coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The second axis in local coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- var len;
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAngAxis1X = this.localAxis1Y * this.localAxis1X - this.localAxis1Z * this.localAxis1Z;
- this.localAngAxis1Y = -this.localAxis1Z * this.localAxis1Y - this.localAxis1X * this.localAxis1X;
- this.localAngAxis1Z = this.localAxis1X * this.localAxis1Z + this.localAxis1Y * this.localAxis1Y;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- // make angle axis 2
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- var tarc = arc.elements;
- this.localAngAxis2X = this.localAngAxis1X * tarc[0] + this.localAngAxis1Y * tarc[1] + this.localAngAxis1Z * tarc[2];
- this.localAngAxis2Y = this.localAngAxis1X * tarc[3] + this.localAngAxis1Y * tarc[4] + this.localAngAxis1Z * tarc[5];
- this.localAngAxis2Z = this.localAngAxis1X * tarc[6] + this.localAngAxis1Y * tarc[7] + this.localAngAxis1Z * tarc[8];
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- // The limit and motor for the rotation
- this.rotationalLimitMotor = new OIMO.LimitMotor(this.nor, false);
- this.r3 = new OIMO.Rotational3Constraint(this, this.rotationalLimitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- // The limit and motor for the translation.
- this.translationalLimitMotor = new OIMO.LimitMotor(this.nor, true);
- this.translationalLimitMotor.lowerLimit = lowerTranslation;
- this.translationalLimitMotor.upperLimit = upperTranslation;
- this.t3 = new OIMO.Translational3Constraint(this, this.translationalLimitMotor, new OIMO.LimitMotor(this.tan, true), new OIMO.LimitMotor(this.bin, true));
- };
- OIMO.SliderJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.SliderJoint.prototype.constructor = OIMO.SliderJoint;
- OIMO.SliderJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var axis1X = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var axis1Y = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var axis1Z = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- var angAxis1X = this.localAngAxis1X * tmpM[0] + this.localAngAxis1Y * tmpM[1] + this.localAngAxis1Z * tmpM[2];
- var angAxis1Y = this.localAngAxis1X * tmpM[3] + this.localAngAxis1Y * tmpM[4] + this.localAngAxis1Z * tmpM[5];
- var angAxis1Z = this.localAngAxis1X * tmpM[6] + this.localAngAxis1Y * tmpM[7] + this.localAngAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var axis2X = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var axis2Y = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var axis2Z = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var angAxis2X = this.localAngAxis2X * tmpM[0] + this.localAngAxis2Y * tmpM[1] + this.localAngAxis2Z * tmpM[2];
- var angAxis2Y = this.localAngAxis2X * tmpM[3] + this.localAngAxis2Y * tmpM[4] + this.localAngAxis2Z * tmpM[5];
- var angAxis2Z = this.localAngAxis2X * tmpM[6] + this.localAngAxis2Y * tmpM[7] + this.localAngAxis2Z * tmpM[8];
- var nx = axis1X * this.body2.inverseMass + axis2X * this.body1.inverseMass;
- var ny = axis1Y * this.body2.inverseMass + axis2Y * this.body1.inverseMass;
- var nz = axis1Z * this.body2.inverseMass + axis2Z * this.body1.inverseMass;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * nx - nz * nz;
- var ty = -nz * ny - nx * nx;
- var tz = nx * nz + ny * ny;
- tmp1X = 1 / OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = ny * tz - nz * ty;
- var by = nz * tx - nx * tz;
- var bz = nx * ty - ny * tx;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- // ----------------------------------------------
- // calculate hinge angle
- // ----------------------------------------------
- if (
- nx * (angAxis1Y * angAxis2Z - angAxis1Z * angAxis2Y) +
- ny * (angAxis1Z * angAxis2X - angAxis1X * angAxis2Z) +
- nz * (angAxis1X * angAxis2Y - angAxis1Y * angAxis2X) < 0
- ) {
- this.rotationalLimitMotor.angle = -this.acosClamp(angAxis1X * angAxis2X + angAxis1Y * angAxis2Y + angAxis1Z * angAxis2Z);
- } else {
- this.rotationalLimitMotor.angle = this.acosClamp(angAxis1X * angAxis2X + angAxis1Y * angAxis2Y + angAxis1Z * angAxis2Z);
- }
- // angular error
- tmp1X = axis1Y * axis2Z - axis1Z * axis2Y;
- tmp1Y = axis1Z * axis2X - axis1X * axis2Z;
- tmp1Z = axis1X * axis2Y - axis1Y * axis2X;
- this.r3.limitMotor2.angle = tx * tmp1X + ty * tmp1Y + tz * tmp1Z;
- this.r3.limitMotor3.angle = bx * tmp1X + by * tmp1Y + bz * tmp1Z;
- this.r3.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.SliderJoint.prototype.solve = function () {
- this.r3.solve();
- this.t3.solve();
- };
- OIMO.SliderJoint.prototype.postSolve = function () {
- };
- OIMO.SliderJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * A wheel joint allows for relative rotation between two rigid bodies along two axes.
- * The wheel joint also allows for relative translation for the suspension.
- * @author saharan
- * @author lo-th
- */
- OIMO.WheelJoint = function (config) {
- OIMO.Joint.call(this, config);
- this.type = OIMO.JOINT_WHEEL;
- // The first axis in local coordinate system.
- this.localAxis1 = new OIMO.Vec3().normalize(config.localAxis1);
- // The second axis in local coordinate system.
- this.localAxis2 = new OIMO.Vec3().normalize(config.localAxis2);
- var len;
- this.localAxis1X = this.localAxis1.x;
- this.localAxis1Y = this.localAxis1.y;
- this.localAxis1Z = this.localAxis1.z;
- this.localAxis2X = this.localAxis2.x;
- this.localAxis2Y = this.localAxis2.y;
- this.localAxis2Z = this.localAxis2.z;
- var dot = this.localAxis1X * this.localAxis2X + this.localAxis1Y * this.localAxis2Y + this.localAxis1Z * this.localAxis2Z;
- if (dot > -1 && dot < 1) {
- this.localAngAxis1X = this.localAxis2X - dot * this.localAxis1X;
- this.localAngAxis1Y = this.localAxis2Y - dot * this.localAxis1Y;
- this.localAngAxis1Z = this.localAxis2Z - dot * this.localAxis1Z;
- this.localAngAxis2X = this.localAxis1X - dot * this.localAxis2X;
- this.localAngAxis2Y = this.localAxis1Y - dot * this.localAxis2Y;
- this.localAngAxis2Z = this.localAxis1Z - dot * this.localAxis2Z;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- len = 1 / OIMO.sqrt(this.localAngAxis2X * this.localAngAxis2X + this.localAngAxis2Y * this.localAngAxis2Y + this.localAngAxis2Z * this.localAngAxis2Z);
- this.localAngAxis2X *= len;
- this.localAngAxis2Y *= len;
- this.localAngAxis2Z *= len;
- } else {
- this.localAngAxis1X = this.localAxis1Y * this.localAxis1X - this.localAxis1Z * this.localAxis1Z;
- this.localAngAxis1Y = -this.localAxis1Z * this.localAxis1Y - this.localAxis1X * this.localAxis1X;
- this.localAngAxis1Z = this.localAxis1X * this.localAxis1Z + this.localAxis1Y * this.localAxis1Y;
- len = 1 / OIMO.sqrt(this.localAngAxis1X * this.localAngAxis1X + this.localAngAxis1Y * this.localAngAxis1Y + this.localAngAxis1Z * this.localAngAxis1Z);
- this.localAngAxis1X *= len;
- this.localAngAxis1Y *= len;
- this.localAngAxis1Z *= len;
- var arc = new OIMO.Mat33().setQuat(new OIMO.Quat().arc(this.localAxis1, this.localAxis2));
- var tarc = arc.elements;
- this.localAngAxis2X = this.localAngAxis1X * tarc[0] + this.localAngAxis1Y * tarc[1] + this.localAngAxis1Z * tarc[2];
- this.localAngAxis2Y = this.localAngAxis1X * tarc[3] + this.localAngAxis1Y * tarc[4] + this.localAngAxis1Z * tarc[5];
- this.localAngAxis2Z = this.localAngAxis1X * tarc[6] + this.localAngAxis1Y * tarc[7] + this.localAngAxis1Z * tarc[8];
- }
- this.nor = new OIMO.Vec3();
- this.tan = new OIMO.Vec3();
- this.bin = new OIMO.Vec3();
- // The translational limit and motor information of the joint.
- this.translationalLimitMotor = new OIMO.LimitMotor(this.tan, true);
- this.translationalLimitMotor.frequency = 8;
- this.translationalLimitMotor.dampingRatio = 1;
- // The first rotational limit and motor information of the joint.
- this.rotationalLimitMotor1 = new OIMO.LimitMotor(this.tan, false);
- // The second rotational limit and motor information of the joint.
- this.rotationalLimitMotor2 = new OIMO.LimitMotor(this.bin, false);
- this.t3 = new OIMO.Translational3Constraint(this, new OIMO.LimitMotor(this.nor, true), this.translationalLimitMotor, new OIMO.LimitMotor(this.bin, true));
- this.t3.weight = 1;
- this.r3 = new OIMO.Rotational3Constraint(this, new OIMO.LimitMotor(this.nor, true), this.rotationalLimitMotor1, this.rotationalLimitMotor2);
- };
- OIMO.WheelJoint.prototype = Object.create(OIMO.Joint.prototype);
- OIMO.WheelJoint.prototype.constructor = OIMO.WheelJoint;
- OIMO.WheelJoint.prototype.preSolve = function (timeStep, invTimeStep) {
- var tmpM;
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- this.updateAnchorPoints();
- tmpM = this.body1.rotation.elements;
- var x1 = this.localAxis1X * tmpM[0] + this.localAxis1Y * tmpM[1] + this.localAxis1Z * tmpM[2];
- var y1 = this.localAxis1X * tmpM[3] + this.localAxis1Y * tmpM[4] + this.localAxis1Z * tmpM[5];
- var z1 = this.localAxis1X * tmpM[6] + this.localAxis1Y * tmpM[7] + this.localAxis1Z * tmpM[8];
- var angAxis1X = this.localAngAxis1X * tmpM[0] + this.localAngAxis1Y * tmpM[1] + this.localAngAxis1Z * tmpM[2];
- var angAxis1Y = this.localAngAxis1X * tmpM[3] + this.localAngAxis1Y * tmpM[4] + this.localAngAxis1Z * tmpM[5];
- var angAxis1Z = this.localAngAxis1X * tmpM[6] + this.localAngAxis1Y * tmpM[7] + this.localAngAxis1Z * tmpM[8];
- tmpM = this.body2.rotation.elements;
- var x2 = this.localAxis2X * tmpM[0] + this.localAxis2Y * tmpM[1] + this.localAxis2Z * tmpM[2];
- var y2 = this.localAxis2X * tmpM[3] + this.localAxis2Y * tmpM[4] + this.localAxis2Z * tmpM[5];
- var z2 = this.localAxis2X * tmpM[6] + this.localAxis2Y * tmpM[7] + this.localAxis2Z * tmpM[8];
- var angAxis2X = this.localAngAxis2X * tmpM[0] + this.localAngAxis2Y * tmpM[1] + this.localAngAxis2Z * tmpM[2];
- var angAxis2Y = this.localAngAxis2X * tmpM[3] + this.localAngAxis2Y * tmpM[4] + this.localAngAxis2Z * tmpM[5];
- var angAxis2Z = this.localAngAxis2X * tmpM[6] + this.localAngAxis2Y * tmpM[7] + this.localAngAxis2Z * tmpM[8];
- this.r3.limitMotor1.angle = x1 * x2 + y1 * y2 + z1 * z2;
- if (x1 * (angAxis1Y * z2 - angAxis1Z * y2) + y1 * (angAxis1Z * x2 - angAxis1X * z2) + z1 * (angAxis1X * y2 - angAxis1Y * x2) < 0) {
- this.rotationalLimitMotor1.angle = -this.acosClamp(angAxis1X * x2 + angAxis1Y * y2 + angAxis1Z * z2);
- } else {
- this.rotationalLimitMotor1.angle = this.acosClamp(angAxis1X * x2 + angAxis1Y * y2 + angAxis1Z * z2);
- }
- if (x2 * (angAxis2Y * z1 - angAxis2Z * y1) + y2 * (angAxis2Z * x1 - angAxis2X * z1) + z2 * (angAxis2X * y1 - angAxis2Y * x1) < 0) {
- this.rotationalLimitMotor2.angle = this.acosClamp(angAxis2X * x1 + angAxis2Y * y1 + angAxis2Z * z1);
- } else {
- this.rotationalLimitMotor2.angle = -this.acosClamp(angAxis2X * x1 + angAxis2Y * y1 + angAxis2Z * z1);
- }
- var nx = y2 * z1 - z2 * y1;
- var ny = z2 * x1 - x2 * z1;
- var nz = x2 * y1 - y2 * x1;
- tmp1X = OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- nx *= tmp1X;
- ny *= tmp1X;
- nz *= tmp1X;
- var tx = ny * z2 - nz * y2;
- var ty = nz * x2 - nx * z2;
- var tz = nx * y2 - ny * x2;
- tmp1X = OIMO.sqrt(tx * tx + ty * ty + tz * tz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- tx *= tmp1X;
- ty *= tmp1X;
- tz *= tmp1X;
- var bx = y1 * nz - z1 * ny;
- var by = z1 * nx - x1 * nz;
- var bz = x1 * ny - y1 * nx;
- tmp1X = OIMO.sqrt(bx * bx + by * by + bz * bz);
- if (tmp1X > 0) tmp1X = 1 / tmp1X;
- bx *= tmp1X;
- by *= tmp1X;
- bz *= tmp1X;
- this.nor.init(nx, ny, nz);
- this.tan.init(tx, ty, tz);
- this.bin.init(bx, by, bz);
- this.r3.preSolve(timeStep, invTimeStep);
- this.t3.preSolve(timeStep, invTimeStep);
- };
- OIMO.WheelJoint.prototype.solve = function () {
- this.r3.solve();
- this.t3.solve();
- };
- OIMO.WheelJoint.prototype.postSolve = function () {
- };
- OIMO.WheelJoint.prototype.acosClamp = function (cos) {
- if (cos > 1) return 0;
- else if (cos < -1) return OIMO.PI;
- else return OIMO.acos(cos);
- };
- /**
- * An angular constraint for all axes for various joints.
- * @author saharan
- */
- OIMO.AngularConstraint = function (joint, targetOrientation) {
- this.joint = joint;
- this.targetOrientation = new OIMO.Quat().invert(targetOrientation);
- this.relativeOrientation = new OIMO.Quat();
- this.ii1 = null;
- this.ii2 = null;
- this.dd = null;
- this.vel = new OIMO.Vec3();
- this.imp = new OIMO.Vec3();
- this.rn0 = new OIMO.Vec3();
- this.rn1 = new OIMO.Vec3();
- this.rn2 = new OIMO.Vec3();
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- };
- OIMO.AngularConstraint.prototype = {
- constructor: OIMO.AngularConstraint,
- preSolve: function (timeStep, invTimeStep) {
- var inv, len, v, vv;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- v = new OIMO.Mat33().add(this.ii1, this.ii2).elements;
- inv = 1 / (v[0] * (v[4] * v[8] - v[7] * v[5]) + v[3] * (v[7] * v[2] - v[1] * v[8]) + v[6] * (v[1] * v[5] - v[4] * v[2]));
- this.dd = new OIMO.Mat33(
- v[4] * v[8] - v[5] * v[7], v[2] * v[7] - v[1] * v[8], v[1] * v[5] - v[2] * v[4],
- v[5] * v[6] - v[3] * v[8], v[0] * v[8] - v[2] * v[6], v[2] * v[3] - v[0] * v[5],
- v[3] * v[7] - v[4] * v[6], v[1] * v[6] - v[0] * v[7], v[0] * v[4] - v[1] * v[3]
- ).multiply(inv);
- this.relativeOrientation.invert(this.b1.orientation);
- this.relativeOrientation.mul(this.targetOrientation, this.relativeOrientation);
- this.relativeOrientation.mul(this.b2.orientation, this.relativeOrientation);
- inv = this.relativeOrientation.s * 2;
- this.vel.scale(this.relativeOrientation, inv);
- len = this.vel.length();
- if (len > 0.02) {
- len = (0.02 - len) / len * invTimeStep * 0.05;
- this.vel.scaleEqual(len);
- } else {
- this.vel.init();
- }
- this.rn1.mulMat(this.ii1, this.imp);
- this.rn2.mulMat(this.ii2, this.imp);
- this.a1.addEqual(this.rn1);
- this.a2.subEqual(this.rn2);
- },
- solve: function () {
- var r = this.a2.clone().subEqual(this.a1).subEqual(this.vel);
- this.rn0.mulMat(this.dd, r);
- this.rn1.mulMat(this.ii1, this.rn0);
- this.rn2.mulMat(this.ii2, this.rn0);
- this.imp.addEqual(this.rn0);
- this.a1.addEqual(this.rn1);
- this.a2.subEqual(this.rn2);
- }
- };
- /**
- * A linear constraint for all axes for various joints.
- * @author saharan
- */
- OIMO.LinearConstraint = function (joint) {
- this.m1 = NaN;
- this.m2 = NaN;
- this.ii1 = null;
- this.ii2 = null;
- this.dd = null;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.ax1x = NaN;
- this.ax1y = NaN;
- this.ax1z = NaN;
- this.ay1x = NaN;
- this.ay1y = NaN;
- this.ay1z = NaN;
- this.az1x = NaN;
- this.az1y = NaN;
- this.az1z = NaN;
- this.ax2x = NaN;
- this.ax2y = NaN;
- this.ax2z = NaN;
- this.ay2x = NaN;
- this.ay2y = NaN;
- this.ay2z = NaN;
- this.az2x = NaN;
- this.az2y = NaN;
- this.az2z = NaN;
- this.vel = NaN;
- this.velx = NaN;
- this.vely = NaN;
- this.velz = NaN;
- this.joint = joint;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.impx = 0;
- this.impy = 0;
- this.impz = 0;
- }
- OIMO.LinearConstraint.prototype = {
- constructor: OIMO.LinearConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.r1x = this.r1.x;
- this.r1y = this.r1.y;
- this.r1z = this.r1.z;
- this.r2x = this.r2.x;
- this.r2y = this.r2.y;
- this.r2z = this.r2.z;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- var ii1 = this.ii1.elements;
- var ii2 = this.ii2.elements;
- this.ax1x = this.r1z * ii1[1] + -this.r1y * ii1[2];
- this.ax1y = this.r1z * ii1[4] + -this.r1y * ii1[5];
- this.ax1z = this.r1z * ii1[7] + -this.r1y * ii1[8];
- this.ay1x = -this.r1z * ii1[0] + this.r1x * ii1[2];
- this.ay1y = -this.r1z * ii1[3] + this.r1x * ii1[5];
- this.ay1z = -this.r1z * ii1[6] + this.r1x * ii1[8];
- this.az1x = this.r1y * ii1[0] + -this.r1x * ii1[1];
- this.az1y = this.r1y * ii1[3] + -this.r1x * ii1[4];
- this.az1z = this.r1y * ii1[6] + -this.r1x * ii1[7];
- this.ax2x = this.r2z * ii2[1] + -this.r2y * ii2[2];
- this.ax2y = this.r2z * ii2[4] + -this.r2y * ii2[5];
- this.ax2z = this.r2z * ii2[7] + -this.r2y * ii2[8];
- this.ay2x = -this.r2z * ii2[0] + this.r2x * ii2[2];
- this.ay2y = -this.r2z * ii2[3] + this.r2x * ii2[5];
- this.ay2z = -this.r2z * ii2[6] + this.r2x * ii2[8];
- this.az2x = this.r2y * ii2[0] + -this.r2x * ii2[1];
- this.az2y = this.r2y * ii2[3] + -this.r2x * ii2[4];
- this.az2z = this.r2y * ii2[6] + -this.r2x * ii2[7];
- // calculate point-to-point mass matrix
- // from impulse equation
- //
- // M = ([/m] - [r^][/I][r^]) ^ -1
- //
- // where
- //
- // [/m] = |1/m, 0, 0|
- // |0, 1/m, 0|
- // |0, 0, 1/m|
- //
- // [r^] = |0, -rz, ry|
- // |rz, 0, -rx|
- // |-ry, rx, 0|
- //
- // [/I] = Inverted moment inertia
- var rxx = this.m1 + this.m2;
- var kk = new OIMO.Mat33(rxx, 0, 0, 0, rxx, 0, 0, 0, rxx);
- var k = kk.elements;
- k[0] += ii1[4] * this.r1z * this.r1z - (ii1[7] + ii1[5]) * this.r1y * this.r1z + ii1[8] * this.r1y * this.r1y;
- k[1] += (ii1[6] * this.r1y + ii1[5] * this.r1x) * this.r1z - ii1[3] * this.r1z * this.r1z - ii1[8] * this.r1x * this.r1y;
- k[2] += (ii1[3] * this.r1y - ii1[4] * this.r1x) * this.r1z - ii1[6] * this.r1y * this.r1y + ii1[7] * this.r1x * this.r1y;
- k[3] += (ii1[2] * this.r1y + ii1[7] * this.r1x) * this.r1z - ii1[1] * this.r1z * this.r1z - ii1[8] * this.r1x * this.r1y;
- k[4] += ii1[0] * this.r1z * this.r1z - (ii1[6] + ii1[2]) * this.r1x * this.r1z + ii1[8] * this.r1x * this.r1x;
- k[5] += (ii1[1] * this.r1x - ii1[0] * this.r1y) * this.r1z - ii1[7] * this.r1x * this.r1x + ii1[6] * this.r1x * this.r1y;
- k[6] += (ii1[1] * this.r1y - ii1[4] * this.r1x) * this.r1z - ii1[2] * this.r1y * this.r1y + ii1[5] * this.r1x * this.r1y;
- k[7] += (ii1[3] * this.r1x - ii1[0] * this.r1y) * this.r1z - ii1[5] * this.r1x * this.r1x + ii1[2] * this.r1x * this.r1y;
- k[8] += ii1[0] * this.r1y * this.r1y - (ii1[3] + ii1[1]) * this.r1x * this.r1y + ii1[4] * this.r1x * this.r1x;
- k[0] += ii2[4] * this.r2z * this.r2z - (ii2[7] + ii2[5]) * this.r2y * this.r2z + ii2[8] * this.r2y * this.r2y;
- k[1] += (ii2[6] * this.r2y + ii2[5] * this.r2x) * this.r2z - ii2[3] * this.r2z * this.r2z - ii2[8] * this.r2x * this.r2y;
- k[2] += (ii2[3] * this.r2y - ii2[4] * this.r2x) * this.r2z - ii2[6] * this.r2y * this.r2y + ii2[7] * this.r2x * this.r2y;
- k[3] += (ii2[2] * this.r2y + ii2[7] * this.r2x) * this.r2z - ii2[1] * this.r2z * this.r2z - ii2[8] * this.r2x * this.r2y;
- k[4] += ii2[0] * this.r2z * this.r2z - (ii2[6] + ii2[2]) * this.r2x * this.r2z + ii2[8] * this.r2x * this.r2x;
- k[5] += (ii2[1] * this.r2x - ii2[0] * this.r2y) * this.r2z - ii2[7] * this.r2x * this.r2x + ii2[6] * this.r2x * this.r2y;
- k[6] += (ii2[1] * this.r2y - ii2[4] * this.r2x) * this.r2z - ii2[2] * this.r2y * this.r2y + ii2[5] * this.r2x * this.r2y;
- k[7] += (ii2[3] * this.r2x - ii2[0] * this.r2y) * this.r2z - ii2[5] * this.r2x * this.r2x + ii2[2] * this.r2x * this.r2y;
- k[8] += ii2[0] * this.r2y * this.r2y - (ii2[3] + ii2[1]) * this.r2x * this.r2y + ii2[4] * this.r2x * this.r2x;
- var inv = 1 / (k[0] * (k[4] * k[8] - k[7] * k[5]) + k[3] * (k[7] * k[2] - k[1] * k[8]) + k[6] * (k[1] * k[5] - k[4] * k[2]));
- this.dd = new OIMO.Mat33(
- k[4] * k[8] - k[5] * k[7], k[2] * k[7] - k[1] * k[8], k[1] * k[5] - k[2] * k[4],
- k[5] * k[6] - k[3] * k[8], k[0] * k[8] - k[2] * k[6], k[2] * k[3] - k[0] * k[5],
- k[3] * k[7] - k[4] * k[6], k[1] * k[6] - k[0] * k[7], k[0] * k[4] - k[1] * k[3]
- ).multiply(inv);
- this.velx = this.p2.x - this.p1.x;
- this.vely = this.p2.y - this.p1.y;
- this.velz = this.p2.z - this.p1.z;
- var len = OIMO.sqrt(this.velx * this.velx + this.vely * this.vely + this.velz * this.velz);
- if (len > 0.005) {
- len = (0.005 - len) / len * invTimeStep * 0.05;
- this.velx *= len;
- this.vely *= len;
- this.velz *= len;
- } else {
- this.velx = 0;
- this.vely = 0;
- this.velz = 0;
- }
- this.impx *= 0.95;
- this.impy *= 0.95;
- this.impz *= 0.95;
- this.l1.x += this.impx * this.m1;
- this.l1.y += this.impy * this.m1;
- this.l1.z += this.impz * this.m1;
- this.a1.x += this.impx * this.ax1x + this.impy * this.ay1x + this.impz * this.az1x;
- this.a1.y += this.impx * this.ax1y + this.impy * this.ay1y + this.impz * this.az1y;
- this.a1.z += this.impx * this.ax1z + this.impy * this.ay1z + this.impz * this.az1z;
- this.l2.x -= this.impx * this.m2;
- this.l2.y -= this.impy * this.m2;
- this.l2.z -= this.impz * this.m2;
- this.a2.x -= this.impx * this.ax2x + this.impy * this.ay2x + this.impz * this.az2x;
- this.a2.y -= this.impx * this.ax2y + this.impy * this.ay2y + this.impz * this.az2y;
- this.a2.z -= this.impx * this.ax2z + this.impy * this.ay2z + this.impz * this.az2z;
- },
- solve: function () {
- var d = this.dd.elements;
- var rvx = this.l2.x - this.l1.x + this.a2.y * this.r2z - this.a2.z * this.r2y - this.a1.y * this.r1z + this.a1.z * this.r1y - this.velx;
- var rvy = this.l2.y - this.l1.y + this.a2.z * this.r2x - this.a2.x * this.r2z - this.a1.z * this.r1x + this.a1.x * this.r1z - this.vely;
- var rvz = this.l2.z - this.l1.z + this.a2.x * this.r2y - this.a2.y * this.r2x - this.a1.x * this.r1y + this.a1.y * this.r1x - this.velz;
- var nimpx = rvx * d[0] + rvy * d[1] + rvz * d[2];
- var nimpy = rvx * d[3] + rvy * d[4] + rvz * d[5];
- var nimpz = rvx * d[6] + rvy * d[7] + rvz * d[8];
- this.impx += nimpx;
- this.impy += nimpy;
- this.impz += nimpz;
- this.l1.x += nimpx * this.m1;
- this.l1.y += nimpy * this.m1;
- this.l1.z += nimpz * this.m1;
- this.a1.x += nimpx * this.ax1x + nimpy * this.ay1x + nimpz * this.az1x;
- this.a1.y += nimpx * this.ax1y + nimpy * this.ay1y + nimpz * this.az1y;
- this.a1.z += nimpx * this.ax1z + nimpy * this.ay1z + nimpz * this.az1z;
- this.l2.x -= nimpx * this.m2;
- this.l2.y -= nimpy * this.m2;
- this.l2.z -= nimpz * this.m2;
- this.a2.x -= nimpx * this.ax2x + nimpy * this.ay2x + nimpz * this.az2x;
- this.a2.y -= nimpx * this.ax2y + nimpy * this.ay2y + nimpz * this.az2y;
- this.a2.z -= nimpx * this.ax2z + nimpy * this.ay2z + nimpz * this.az2z;
- }
- }
- /**
- * A three-axis rotational constraint for various joints.
- * @author saharan
- */
- OIMO.Rotational3Constraint = function (joint, limitMotor1, limitMotor2, limitMotor3) {
- this.cfm1 = NaN;
- this.cfm2 = NaN;
- this.cfm3 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.ax1 = NaN;
- this.ay1 = NaN;
- this.az1 = NaN;
- this.ax2 = NaN;
- this.ay2 = NaN;
- this.az2 = NaN;
- this.ax3 = NaN;
- this.ay3 = NaN;
- this.az3 = NaN;
- this.a1x1 = NaN; // jacoians
- this.a1y1 = NaN;
- this.a1z1 = NaN;
- this.a2x1 = NaN;
- this.a2y1 = NaN;
- this.a2z1 = NaN;
- this.a1x2 = NaN;
- this.a1y2 = NaN;
- this.a1z2 = NaN;
- this.a2x2 = NaN;
- this.a2y2 = NaN;
- this.a2z2 = NaN;
- this.a1x3 = NaN;
- this.a1y3 = NaN;
- this.a1z3 = NaN;
- this.a2x3 = NaN;
- this.a2y3 = NaN;
- this.a2z3 = NaN;
- this.lowerLimit1 = NaN;
- this.upperLimit1 = NaN;
- this.limitVelocity1 = NaN;
- this.limitState1 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor1 = false;
- this.motorSpeed1 = NaN;
- this.maxMotorForce1 = NaN;
- this.maxMotorImpulse1 = NaN;
- this.lowerLimit2 = NaN;
- this.upperLimit2 = NaN;
- this.limitVelocity2 = NaN;
- this.limitState2 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor2 = false;
- this.motorSpeed2 = NaN;
- this.maxMotorForce2 = NaN;
- this.maxMotorImpulse2 = NaN;
- this.lowerLimit3 = NaN;
- this.upperLimit3 = NaN;
- this.limitVelocity3 = NaN;
- this.limitState3 = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor3 = false;
- this.motorSpeed3 = NaN;
- this.maxMotorForce3 = NaN;
- this.maxMotorImpulse3 = NaN;
- this.k00 = NaN; // K = J*M*JT
- this.k01 = NaN;
- this.k02 = NaN;
- this.k10 = NaN;
- this.k11 = NaN;
- this.k12 = NaN;
- this.k20 = NaN;
- this.k21 = NaN;
- this.k22 = NaN;
- this.kv00 = NaN; // diagonals without CFMs
- this.kv11 = NaN;
- this.kv22 = NaN;
- this.dv00 = NaN; // ...inverted
- this.dv11 = NaN;
- this.dv22 = NaN;
- this.d00 = NaN; // K^-1
- this.d01 = NaN;
- this.d02 = NaN;
- this.d10 = NaN;
- this.d11 = NaN;
- this.d12 = NaN;
- this.d20 = NaN;
- this.d21 = NaN;
- this.d22 = NaN;
- this.limitMotor1 = limitMotor1;
- this.limitMotor2 = limitMotor2;
- this.limitMotor3 = limitMotor3;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse1 = 0;
- this.motorImpulse1 = 0;
- this.limitImpulse2 = 0;
- this.motorImpulse2 = 0;
- this.limitImpulse3 = 0;
- this.motorImpulse3 = 0;
- }
- OIMO.Rotational3Constraint.prototype = {
- constructor: OIMO.Rotational3Constraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax1 = this.limitMotor1.axis.x;
- this.ay1 = this.limitMotor1.axis.y;
- this.az1 = this.limitMotor1.axis.z;
- this.ax2 = this.limitMotor2.axis.x;
- this.ay2 = this.limitMotor2.axis.y;
- this.az2 = this.limitMotor2.axis.z;
- this.ax3 = this.limitMotor3.axis.x;
- this.ay3 = this.limitMotor3.axis.y;
- this.az3 = this.limitMotor3.axis.z;
- this.lowerLimit1 = this.limitMotor1.lowerLimit;
- this.upperLimit1 = this.limitMotor1.upperLimit;
- this.motorSpeed1 = this.limitMotor1.motorSpeed;
- this.maxMotorForce1 = this.limitMotor1.maxMotorForce;
- this.enableMotor1 = this.maxMotorForce1 > 0;
- this.lowerLimit2 = this.limitMotor2.lowerLimit;
- this.upperLimit2 = this.limitMotor2.upperLimit;
- this.motorSpeed2 = this.limitMotor2.motorSpeed;
- this.maxMotorForce2 = this.limitMotor2.maxMotorForce;
- this.enableMotor2 = this.maxMotorForce2 > 0;
- this.lowerLimit3 = this.limitMotor3.lowerLimit;
- this.upperLimit3 = this.limitMotor3.upperLimit;
- this.motorSpeed3 = this.limitMotor3.motorSpeed;
- this.maxMotorForce3 = this.limitMotor3.maxMotorForce;
- this.enableMotor3 = this.maxMotorForce3 > 0;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var frequency1 = this.limitMotor1.frequency;
- var frequency2 = this.limitMotor2.frequency;
- var frequency3 = this.limitMotor3.frequency;
- var enableSpring1 = frequency1 > 0;
- var enableSpring2 = frequency2 > 0;
- var enableSpring3 = frequency3 > 0;
- var enableLimit1 = this.lowerLimit1 <= this.upperLimit1;
- var enableLimit2 = this.lowerLimit2 <= this.upperLimit2;
- var enableLimit3 = this.lowerLimit3 <= this.upperLimit3;
- var angle1 = this.limitMotor1.angle;
- if (enableLimit1) {
- if (this.lowerLimit1 == this.upperLimit1) {
- if (this.limitState1 != 0) {
- this.limitState1 = 0;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - angle1;
- } else if (angle1 < this.lowerLimit1) {
- if (this.limitState1 != -1) {
- this.limitState1 = -1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - angle1;
- } else if (angle1 > this.upperLimit1) {
- if (this.limitState1 != 1) {
- this.limitState1 = 1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.upperLimit1 - angle1;
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- this.limitVelocity1 = 0;
- }
- if (!enableSpring1) {
- if (this.limitVelocity1 > 0.02) this.limitVelocity1 -= 0.02;
- else if (this.limitVelocity1 < -0.02) this.limitVelocity1 += 0.02;
- else this.limitVelocity1 = 0;
- }
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- }
- var angle2 = this.limitMotor2.angle;
- if (enableLimit2) {
- if (this.lowerLimit2 == this.upperLimit2) {
- if (this.limitState2 != 0) {
- this.limitState2 = 0;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - angle2;
- } else if (angle2 < this.lowerLimit2) {
- if (this.limitState2 != -1) {
- this.limitState2 = -1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - angle2;
- } else if (angle2 > this.upperLimit2) {
- if (this.limitState2 != 1) {
- this.limitState2 = 1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.upperLimit2 - angle2;
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- this.limitVelocity2 = 0;
- }
- if (!enableSpring2) {
- if (this.limitVelocity2 > 0.02) this.limitVelocity2 -= 0.02;
- else if (this.limitVelocity2 < -0.02) this.limitVelocity2 += 0.02;
- else this.limitVelocity2 = 0;
- }
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- }
- var angle3 = this.limitMotor3.angle;
- if (enableLimit3) {
- if (this.lowerLimit3 == this.upperLimit3) {
- if (this.limitState3 != 0) {
- this.limitState3 = 0;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - angle3;
- } else if (angle3 < this.lowerLimit3) {
- if (this.limitState3 != -1) {
- this.limitState3 = -1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - angle3;
- } else if (angle3 > this.upperLimit3) {
- if (this.limitState3 != 1) {
- this.limitState3 = 1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.upperLimit3 - angle3;
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- this.limitVelocity3 = 0;
- }
- if (!enableSpring3) {
- if (this.limitVelocity3 > 0.02) this.limitVelocity3 -= 0.02;
- else if (this.limitVelocity3 < -0.02) this.limitVelocity3 += 0.02;
- else this.limitVelocity3 = 0;
- }
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- }
- if (this.enableMotor1 && (this.limitState1 != 0 || enableSpring1)) {
- this.maxMotorImpulse1 = this.maxMotorForce1 * timeStep;
- } else {
- this.motorImpulse1 = 0;
- this.maxMotorImpulse1 = 0;
- }
- if (this.enableMotor2 && (this.limitState2 != 0 || enableSpring2)) {
- this.maxMotorImpulse2 = this.maxMotorForce2 * timeStep;
- } else {
- this.motorImpulse2 = 0;
- this.maxMotorImpulse2 = 0;
- }
- if (this.enableMotor3 && (this.limitState3 != 0 || enableSpring3)) {
- this.maxMotorImpulse3 = this.maxMotorForce3 * timeStep;
- } else {
- this.motorImpulse3 = 0;
- this.maxMotorImpulse3 = 0;
- }
- // build jacobians
- this.a1x1 = this.ax1 * this.i1e00 + this.ay1 * this.i1e01 + this.az1 * this.i1e02;
- this.a1y1 = this.ax1 * this.i1e10 + this.ay1 * this.i1e11 + this.az1 * this.i1e12;
- this.a1z1 = this.ax1 * this.i1e20 + this.ay1 * this.i1e21 + this.az1 * this.i1e22;
- this.a2x1 = this.ax1 * this.i2e00 + this.ay1 * this.i2e01 + this.az1 * this.i2e02;
- this.a2y1 = this.ax1 * this.i2e10 + this.ay1 * this.i2e11 + this.az1 * this.i2e12;
- this.a2z1 = this.ax1 * this.i2e20 + this.ay1 * this.i2e21 + this.az1 * this.i2e22;
- this.a1x2 = this.ax2 * this.i1e00 + this.ay2 * this.i1e01 + this.az2 * this.i1e02;
- this.a1y2 = this.ax2 * this.i1e10 + this.ay2 * this.i1e11 + this.az2 * this.i1e12;
- this.a1z2 = this.ax2 * this.i1e20 + this.ay2 * this.i1e21 + this.az2 * this.i1e22;
- this.a2x2 = this.ax2 * this.i2e00 + this.ay2 * this.i2e01 + this.az2 * this.i2e02;
- this.a2y2 = this.ax2 * this.i2e10 + this.ay2 * this.i2e11 + this.az2 * this.i2e12;
- this.a2z2 = this.ax2 * this.i2e20 + this.ay2 * this.i2e21 + this.az2 * this.i2e22;
- this.a1x3 = this.ax3 * this.i1e00 + this.ay3 * this.i1e01 + this.az3 * this.i1e02;
- this.a1y3 = this.ax3 * this.i1e10 + this.ay3 * this.i1e11 + this.az3 * this.i1e12;
- this.a1z3 = this.ax3 * this.i1e20 + this.ay3 * this.i1e21 + this.az3 * this.i1e22;
- this.a2x3 = this.ax3 * this.i2e00 + this.ay3 * this.i2e01 + this.az3 * this.i2e02;
- this.a2y3 = this.ax3 * this.i2e10 + this.ay3 * this.i2e11 + this.az3 * this.i2e12;
- this.a2z3 = this.ax3 * this.i2e20 + this.ay3 * this.i2e21 + this.az3 * this.i2e22;
- // build an impulse matrix
- this.k00 = this.ax1 * (this.a1x1 + this.a2x1) + this.ay1 * (this.a1y1 + this.a2y1) + this.az1 * (this.a1z1 + this.a2z1);
- this.k01 = this.ax1 * (this.a1x2 + this.a2x2) + this.ay1 * (this.a1y2 + this.a2y2) + this.az1 * (this.a1z2 + this.a2z2);
- this.k02 = this.ax1 * (this.a1x3 + this.a2x3) + this.ay1 * (this.a1y3 + this.a2y3) + this.az1 * (this.a1z3 + this.a2z3);
- this.k10 = this.ax2 * (this.a1x1 + this.a2x1) + this.ay2 * (this.a1y1 + this.a2y1) + this.az2 * (this.a1z1 + this.a2z1);
- this.k11 = this.ax2 * (this.a1x2 + this.a2x2) + this.ay2 * (this.a1y2 + this.a2y2) + this.az2 * (this.a1z2 + this.a2z2);
- this.k12 = this.ax2 * (this.a1x3 + this.a2x3) + this.ay2 * (this.a1y3 + this.a2y3) + this.az2 * (this.a1z3 + this.a2z3);
- this.k20 = this.ax3 * (this.a1x1 + this.a2x1) + this.ay3 * (this.a1y1 + this.a2y1) + this.az3 * (this.a1z1 + this.a2z1);
- this.k21 = this.ax3 * (this.a1x2 + this.a2x2) + this.ay3 * (this.a1y2 + this.a2y2) + this.az3 * (this.a1z2 + this.a2z2);
- this.k22 = this.ax3 * (this.a1x3 + this.a2x3) + this.ay3 * (this.a1y3 + this.a2y3) + this.az3 * (this.a1z3 + this.a2z3);
- this.kv00 = this.k00;
- this.kv11 = this.k11;
- this.kv22 = this.k22;
- this.dv00 = 1 / this.kv00;
- this.dv11 = 1 / this.kv11;
- this.dv22 = 1 / this.kv22;
- if (enableSpring1 && this.limitState1 != 2) {
- var omega = 6.2831853 * frequency1;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor1.dampingRatio * omega);
- this.cfm1 = this.kv00 * dmp;
- this.limitVelocity1 *= k * dmp;
- } else {
- this.cfm1 = 0;
- this.limitVelocity1 *= invTimeStep * 0.05;
- }
- if (enableSpring2 && this.limitState2 != 2) {
- omega = 6.2831853 * frequency2;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor2.dampingRatio * omega);
- this.cfm2 = this.kv11 * dmp;
- this.limitVelocity2 *= k * dmp;
- } else {
- this.cfm2 = 0;
- this.limitVelocity2 *= invTimeStep * 0.05;
- }
- if (enableSpring3 && this.limitState3 != 2) {
- omega = 6.2831853 * frequency3;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor3.dampingRatio * omega);
- this.cfm3 = this.kv22 * dmp;
- this.limitVelocity3 *= k * dmp;
- } else {
- this.cfm3 = 0;
- this.limitVelocity3 *= invTimeStep * 0.05;
- }
- this.k00 += this.cfm1;
- this.k11 += this.cfm2;
- this.k22 += this.cfm3;
- var inv = 1 / (
- this.k00 * (this.k11 * this.k22 - this.k21 * this.k12) +
- this.k10 * (this.k21 * this.k02 - this.k01 * this.k22) +
- this.k20 * (this.k01 * this.k12 - this.k11 * this.k02)
- );
- this.d00 = (this.k11 * this.k22 - this.k12 * this.k21) * inv;
- this.d01 = (this.k02 * this.k21 - this.k01 * this.k22) * inv;
- this.d02 = (this.k01 * this.k12 - this.k02 * this.k11) * inv;
- this.d10 = (this.k12 * this.k20 - this.k10 * this.k22) * inv;
- this.d11 = (this.k00 * this.k22 - this.k02 * this.k20) * inv;
- this.d12 = (this.k02 * this.k10 - this.k00 * this.k12) * inv;
- this.d20 = (this.k10 * this.k21 - this.k11 * this.k20) * inv;
- this.d21 = (this.k01 * this.k20 - this.k00 * this.k21) * inv;
- this.d22 = (this.k00 * this.k11 - this.k01 * this.k10) * inv;
- this.limitImpulse1 *= 0.95;
- this.motorImpulse1 *= 0.95;
- this.limitImpulse2 *= 0.95;
- this.motorImpulse2 *= 0.95;
- this.limitImpulse3 *= 0.95;
- this.motorImpulse3 *= 0.95;
- var totalImpulse1 = this.limitImpulse1 + this.motorImpulse1;
- var totalImpulse2 = this.limitImpulse2 + this.motorImpulse2;
- var totalImpulse3 = this.limitImpulse3 + this.motorImpulse3;
- this.a1.x += totalImpulse1 * this.a1x1 + totalImpulse2 * this.a1x2 + totalImpulse3 * this.a1x3;
- this.a1.y += totalImpulse1 * this.a1y1 + totalImpulse2 * this.a1y2 + totalImpulse3 * this.a1y3;
- this.a1.z += totalImpulse1 * this.a1z1 + totalImpulse2 * this.a1z2 + totalImpulse3 * this.a1z3;
- this.a2.x -= totalImpulse1 * this.a2x1 + totalImpulse2 * this.a2x2 + totalImpulse3 * this.a2x3;
- this.a2.y -= totalImpulse1 * this.a2y1 + totalImpulse2 * this.a2y2 + totalImpulse3 * this.a2y3;
- this.a2.z -= totalImpulse1 * this.a2z1 + totalImpulse2 * this.a2z2 + totalImpulse3 * this.a2z3;
- },
- solve_: function () {
- var rvx = this.a2.x - this.a1.x;
- var rvy = this.a2.y - this.a1.y;
- var rvz = this.a2.z - this.a1.z;
- this.limitVelocity3 = 30;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1 - this.limitVelocity1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2 - this.limitVelocity2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3 - this.limitVelocity3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- this.a1.x += dLimitImpulse1 * this.a1x1 + dLimitImpulse2 * this.a1x2 + dLimitImpulse3 * this.a1x3;
- this.a1.y += dLimitImpulse1 * this.a1y1 + dLimitImpulse2 * this.a1y2 + dLimitImpulse3 * this.a1y3;
- this.a1.z += dLimitImpulse1 * this.a1z1 + dLimitImpulse2 * this.a1z2 + dLimitImpulse3 * this.a1z3;
- this.a2.x -= dLimitImpulse1 * this.a2x1 + dLimitImpulse2 * this.a2x2 + dLimitImpulse3 * this.a2x3;
- this.a2.y -= dLimitImpulse1 * this.a2y1 + dLimitImpulse2 * this.a2y2 + dLimitImpulse3 * this.a2y3;
- this.a2.z -= dLimitImpulse1 * this.a2z1 + dLimitImpulse2 * this.a2z2 + dLimitImpulse3 * this.a2z3;
- },
- solve: function () {
- var rvx = this.a2.x - this.a1.x;
- var rvy = this.a2.y - this.a1.y;
- var rvz = this.a2.z - this.a1.z;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3;
- var oldMotorImpulse1 = this.motorImpulse1;
- var oldMotorImpulse2 = this.motorImpulse2;
- var oldMotorImpulse3 = this.motorImpulse3;
- var dMotorImpulse1 = 0;
- var dMotorImpulse2 = 0;
- var dMotorImpulse3 = 0;
- if (this.enableMotor1) {
- dMotorImpulse1 = (rvn1 - this.motorSpeed1) * this.dv00;
- this.motorImpulse1 += dMotorImpulse1;
- if (this.motorImpulse1 > this.maxMotorImpulse1) { // clamp motor impulse
- this.motorImpulse1 = this.maxMotorImpulse1;
- } else if (this.motorImpulse1 < -this.maxMotorImpulse1) {
- this.motorImpulse1 = -this.maxMotorImpulse1;
- }
- dMotorImpulse1 = this.motorImpulse1 - oldMotorImpulse1;
- }
- if (this.enableMotor2) {
- dMotorImpulse2 = (rvn2 - this.motorSpeed2) * this.dv11;
- this.motorImpulse2 += dMotorImpulse2;
- if (this.motorImpulse2 > this.maxMotorImpulse2) { // clamp motor impulse
- this.motorImpulse2 = this.maxMotorImpulse2;
- } else if (this.motorImpulse2 < -this.maxMotorImpulse2) {
- this.motorImpulse2 = -this.maxMotorImpulse2;
- }
- dMotorImpulse2 = this.motorImpulse2 - oldMotorImpulse2;
- }
- if (this.enableMotor3) {
- dMotorImpulse3 = (rvn3 - this.motorSpeed3) * this.dv22;
- this.motorImpulse3 += dMotorImpulse3;
- if (this.motorImpulse3 > this.maxMotorImpulse3) { // clamp motor impulse
- this.motorImpulse3 = this.maxMotorImpulse3;
- } else if (this.motorImpulse3 < -this.maxMotorImpulse3) {
- this.motorImpulse3 = -this.maxMotorImpulse3;
- }
- dMotorImpulse3 = this.motorImpulse3 - oldMotorImpulse3;
- }
- // apply motor impulse to relative velocity
- rvn1 += dMotorImpulse1 * this.kv00 + dMotorImpulse2 * this.k01 + dMotorImpulse3 * this.k02;
- rvn2 += dMotorImpulse1 * this.k10 + dMotorImpulse2 * this.kv11 + dMotorImpulse3 * this.k12;
- rvn3 += dMotorImpulse1 * this.k20 + dMotorImpulse2 * this.k21 + dMotorImpulse3 * this.kv22;
- // subtract target velocity and applied impulse
- rvn1 -= this.limitVelocity1 + this.limitImpulse1 * this.cfm1;
- rvn2 -= this.limitVelocity2 + this.limitImpulse2 * this.cfm2;
- rvn3 -= this.limitVelocity3 + this.limitImpulse3 * this.cfm3;
- var oldLimitImpulse1 = this.limitImpulse1;
- var oldLimitImpulse2 = this.limitImpulse2;
- var oldLimitImpulse3 = this.limitImpulse3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- // clamp
- var clampState = 0;
- if (this.limitState1 == 2 || this.limitImpulse1 * this.limitState1 < 0) {
- dLimitImpulse1 = -oldLimitImpulse1;
- rvn2 += dLimitImpulse1 * this.k10;
- rvn3 += dLimitImpulse1 * this.k20;
- clampState |= 1;
- }
- if (this.limitState2 == 2 || this.limitImpulse2 * this.limitState2 < 0) {
- dLimitImpulse2 = -oldLimitImpulse2;
- rvn1 += dLimitImpulse2 * this.k01;
- rvn3 += dLimitImpulse2 * this.k21;
- clampState |= 2;
- }
- if (this.limitState3 == 2 || this.limitImpulse3 * this.limitState3 < 0) {
- dLimitImpulse3 = -oldLimitImpulse3;
- rvn1 += dLimitImpulse3 * this.k02;
- rvn2 += dLimitImpulse3 * this.k12;
- clampState |= 4;
- }
- // update un-clamped impulse
- // TODO: isolate division
- var det;
- switch (clampState) {
- case 1: // update 2 3
- det = 1 / (this.k11 * this.k22 - this.k12 * this.k21);
- dLimitImpulse2 = (this.k22 * rvn2 + -this.k12 * rvn3) * det;
- dLimitImpulse3 = (-this.k21 * rvn2 + this.k11 * rvn3) * det;
- break;
- case 2: // update 1 3
- det = 1 / (this.k00 * this.k22 - this.k02 * this.k20);
- dLimitImpulse1 = (this.k22 * rvn1 + -this.k02 * rvn3) * det;
- dLimitImpulse3 = (-this.k20 * rvn1 + this.k00 * rvn3) * det;
- break;
- case 3: // update 3
- dLimitImpulse3 = rvn3 / this.k22;
- break;
- case 4: // update 1 2
- det = 1 / (this.k00 * this.k11 - this.k01 * this.k10);
- dLimitImpulse1 = (this.k11 * rvn1 + -this.k01 * rvn2) * det;
- dLimitImpulse2 = (-this.k10 * rvn1 + this.k00 * rvn2) * det;
- break;
- case 5: // update 2
- dLimitImpulse2 = rvn2 / this.k11;
- break;
- case 6: // update 1
- dLimitImpulse1 = rvn1 / this.k00;
- break;
- }
- this.limitImpulse1 = dLimitImpulse1 + oldLimitImpulse1;
- this.limitImpulse2 = dLimitImpulse2 + oldLimitImpulse2;
- this.limitImpulse3 = dLimitImpulse3 + oldLimitImpulse3;
- var dImpulse1 = dMotorImpulse1 + dLimitImpulse1;
- var dImpulse2 = dMotorImpulse2 + dLimitImpulse2;
- var dImpulse3 = dMotorImpulse3 + dLimitImpulse3;
- // apply impulse
- this.a1.x += dImpulse1 * this.a1x1 + dImpulse2 * this.a1x2 + dImpulse3 * this.a1x3;
- this.a1.y += dImpulse1 * this.a1y1 + dImpulse2 * this.a1y2 + dImpulse3 * this.a1y3;
- this.a1.z += dImpulse1 * this.a1z1 + dImpulse2 * this.a1z2 + dImpulse3 * this.a1z3;
- this.a2.x -= dImpulse1 * this.a2x1 + dImpulse2 * this.a2x2 + dImpulse3 * this.a2x3;
- this.a2.y -= dImpulse1 * this.a2y1 + dImpulse2 * this.a2y2 + dImpulse3 * this.a2y3;
- this.a2.z -= dImpulse1 * this.a2z1 + dImpulse2 * this.a2z2 + dImpulse3 * this.a2z3;
- rvx = this.a2.x - this.a1.x;
- rvy = this.a2.y - this.a1.y;
- rvz = this.a2.z - this.a1.z;
- rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- }
- }
- /**
- * A rotational constraint for various joints.
- * @author saharan
- */
- OIMO.RotationalConstraint = function (joint, limitMotor) {
- this.cfm = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.motorDenom = NaN;
- this.invMotorDenom = NaN;
- this.invDenom = NaN;
- this.ax = NaN;
- this.ay = NaN;
- this.az = NaN;
- this.a1x = NaN;
- this.a1y = NaN;
- this.a1z = NaN;
- this.a2x = NaN;
- this.a2y = NaN;
- this.a2z = NaN;
- this.enableLimit = false;
- this.lowerLimit = NaN;
- this.upperLimit = NaN;
- this.limitVelocity = NaN;
- this.limitState = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor = false;
- this.motorSpeed = NaN;
- this.maxMotorForce = NaN;
- this.maxMotorImpulse = NaN;
- this.limitMotor = limitMotor;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse = 0;
- this.motorImpulse = 0;
- }
- OIMO.RotationalConstraint.prototype = {
- constructor: OIMO.RotationalConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax = this.limitMotor.axis.x;
- this.ay = this.limitMotor.axis.y;
- this.az = this.limitMotor.axis.z;
- this.lowerLimit = this.limitMotor.lowerLimit;
- this.upperLimit = this.limitMotor.upperLimit;
- this.motorSpeed = this.limitMotor.motorSpeed;
- this.maxMotorForce = this.limitMotor.maxMotorForce;
- this.enableMotor = this.maxMotorForce > 0;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var frequency = this.limitMotor.frequency;
- var enableSpring = frequency > 0;
- var enableLimit = this.lowerLimit <= this.upperLimit;
- var angle = this.limitMotor.angle;
- if (enableLimit) {
- if (this.lowerLimit == this.upperLimit) {
- if (this.limitState != 0) {
- this.limitState = 0;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - angle;
- } else if (angle < this.lowerLimit) {
- if (this.limitState != -1) {
- this.limitState = -1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - angle;
- } else if (angle > this.upperLimit) {
- if (this.limitState != 1) {
- this.limitState = 1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.upperLimit - angle;
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- this.limitVelocity = 0;
- }
- if (!enableSpring) {
- if (this.limitVelocity > 0.02) this.limitVelocity -= 0.02;
- else if (this.limitVelocity < -0.02) this.limitVelocity += 0.02;
- else this.limitVelocity = 0;
- }
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- }
- if (this.enableMotor && (this.limitState != 0 || enableSpring)) {
- this.maxMotorImpulse = this.maxMotorForce * timeStep;
- } else {
- this.motorImpulse = 0;
- this.maxMotorImpulse = 0;
- }
- this.a1x = this.ax * this.i1e00 + this.ay * this.i1e01 + this.az * this.i1e02;
- this.a1y = this.ax * this.i1e10 + this.ay * this.i1e11 + this.az * this.i1e12;
- this.a1z = this.ax * this.i1e20 + this.ay * this.i1e21 + this.az * this.i1e22;
- this.a2x = this.ax * this.i2e00 + this.ay * this.i2e01 + this.az * this.i2e02;
- this.a2y = this.ax * this.i2e10 + this.ay * this.i2e11 + this.az * this.i2e12;
- this.a2z = this.ax * this.i2e20 + this.ay * this.i2e21 + this.az * this.i2e22;
- this.motorDenom = this.ax * (this.a1x + this.a2x) + this.ay * (this.a1y + this.a2y) + this.az * (this.a1z + this.a2z);
- this.invMotorDenom = 1 / this.motorDenom;
- if (enableSpring && this.limitState != 2) {
- var omega = 6.2831853 * frequency;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor.dampingRatio * omega);
- this.cfm = this.motorDenom * dmp;
- this.limitVelocity *= k * dmp;
- } else {
- this.cfm = 0;
- this.limitVelocity *= invTimeStep * 0.05;
- }
- this.invDenom = 1 / (this.motorDenom + this.cfm);
- this.limitImpulse *= 0.95;
- this.motorImpulse *= 0.95;
- var totalImpulse = this.limitImpulse + this.motorImpulse;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- },
- solve: function () {
- var rvn = this.ax * (this.a2.x - this.a1.x) + this.ay * (this.a2.y - this.a1.y) + this.az * (this.a2.z - this.a1.z);
- // motor part
- var newMotorImpulse;
- if (this.enableMotor) {
- newMotorImpulse = (rvn - this.motorSpeed) * this.invMotorDenom;
- var oldMotorImpulse = this.motorImpulse;
- this.motorImpulse += newMotorImpulse;
- if (this.motorImpulse > this.maxMotorImpulse) this.motorImpulse = this.maxMotorImpulse;
- else if (this.motorImpulse < -this.maxMotorImpulse) this.motorImpulse = -this.maxMotorImpulse;
- newMotorImpulse = this.motorImpulse - oldMotorImpulse;
- rvn -= newMotorImpulse * this.motorDenom;
- } else newMotorImpulse = 0;
- // limit part
- var newLimitImpulse;
- if (this.limitState != 2) {
- newLimitImpulse = (rvn - this.limitVelocity - this.limitImpulse * this.cfm) * this.invDenom;
- var oldLimitImpulse = this.limitImpulse;
- this.limitImpulse += newLimitImpulse;
- if (this.limitImpulse * this.limitState < 0) this.limitImpulse = 0;
- newLimitImpulse = this.limitImpulse - oldLimitImpulse;
- } else newLimitImpulse = 0;
- var totalImpulse = newLimitImpulse + newMotorImpulse;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- }
- }
- /**
- * A three-axis translational constraint for various joints.
- * @author saharan
- */
- OIMO.Translational3Constraint = function (joint, limitMotor1, limitMotor2, limitMotor3) {
- this.m1 = NaN;
- this.m2 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.ax1 = NaN;
- this.ay1 = NaN;
- this.az1 = NaN;
- this.ax2 = NaN;
- this.ay2 = NaN;
- this.az2 = NaN;
- this.ax3 = NaN;
- this.ay3 = NaN;
- this.az3 = NaN;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.t1x1 = NaN;// jacobians
- this.t1y1 = NaN;
- this.t1z1 = NaN;
- this.t2x1 = NaN;
- this.t2y1 = NaN;
- this.t2z1 = NaN;
- this.l1x1 = NaN;
- this.l1y1 = NaN;
- this.l1z1 = NaN;
- this.l2x1 = NaN;
- this.l2y1 = NaN;
- this.l2z1 = NaN;
- this.a1x1 = NaN;
- this.a1y1 = NaN;
- this.a1z1 = NaN;
- this.a2x1 = NaN;
- this.a2y1 = NaN;
- this.a2z1 = NaN;
- this.t1x2 = NaN;
- this.t1y2 = NaN;
- this.t1z2 = NaN;
- this.t2x2 = NaN;
- this.t2y2 = NaN;
- this.t2z2 = NaN;
- this.l1x2 = NaN;
- this.l1y2 = NaN;
- this.l1z2 = NaN;
- this.l2x2 = NaN;
- this.l2y2 = NaN;
- this.l2z2 = NaN;
- this.a1x2 = NaN;
- this.a1y2 = NaN;
- this.a1z2 = NaN;
- this.a2x2 = NaN;
- this.a2y2 = NaN;
- this.a2z2 = NaN;
- this.t1x3 = NaN;
- this.t1y3 = NaN;
- this.t1z3 = NaN;
- this.t2x3 = NaN;
- this.t2y3 = NaN;
- this.t2z3 = NaN;
- this.l1x3 = NaN;
- this.l1y3 = NaN;
- this.l1z3 = NaN;
- this.l2x3 = NaN;
- this.l2y3 = NaN;
- this.l2z3 = NaN;
- this.a1x3 = NaN;
- this.a1y3 = NaN;
- this.a1z3 = NaN;
- this.a2x3 = NaN;
- this.a2y3 = NaN;
- this.a2z3 = NaN;
- this.lowerLimit1 = NaN;
- this.upperLimit1 = NaN;
- this.limitVelocity1 = NaN;
- this.limitState1 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor1 = false;
- this.motorSpeed1 = NaN;
- this.maxMotorForce1 = NaN;
- this.maxMotorImpulse1 = NaN;
- this.lowerLimit2 = NaN;
- this.upperLimit2 = NaN;
- this.limitVelocity2 = NaN;
- this.limitState2 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor2 = false;
- this.motorSpeed2 = NaN;
- this.maxMotorForce2 = NaN;
- this.maxMotorImpulse2 = NaN;
- this.lowerLimit3 = NaN;
- this.upperLimit3 = NaN;
- this.limitVelocity3 = NaN;
- this.limitState3 = 0; // -1: at lower, 0: locked, 1: at upper, 2: unlimited
- this.enableMotor3 = false;
- this.motorSpeed3 = NaN;
- this.maxMotorForce3 = NaN;
- this.maxMotorImpulse3 = NaN;
- this.k00 = NaN; // K = J*M*JT
- this.k01 = NaN;
- this.k02 = NaN;
- this.k10 = NaN;
- this.k11 = NaN;
- this.k12 = NaN;
- this.k20 = NaN;
- this.k21 = NaN;
- this.k22 = NaN;
- this.kv00 = NaN; // diagonals without CFMs
- this.kv11 = NaN;
- this.kv22 = NaN;
- this.dv00 = NaN; // ...inverted
- this.dv11 = NaN;
- this.dv22 = NaN;
- this.d00 = NaN; // K^-1
- this.d01 = NaN;
- this.d02 = NaN;
- this.d10 = NaN;
- this.d11 = NaN;
- this.d12 = NaN;
- this.d20 = NaN;
- this.d21 = NaN;
- this.d22 = NaN;
- this.limitMotor1 = limitMotor1;
- this.limitMotor2 = limitMotor2;
- this.limitMotor3 = limitMotor3;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse1 = 0;
- this.motorImpulse1 = 0;
- this.limitImpulse2 = 0;
- this.motorImpulse2 = 0;
- this.limitImpulse3 = 0;
- this.motorImpulse3 = 0;
- this.cfm1 = 0;// Constraint Force Mixing
- this.cfm2 = 0;
- this.cfm3 = 0;
- this.weight = -1;
- }
- OIMO.Translational3Constraint.prototype = {
- constructor: OIMO.Translational3Constraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax1 = this.limitMotor1.axis.x;
- this.ay1 = this.limitMotor1.axis.y;
- this.az1 = this.limitMotor1.axis.z;
- this.ax2 = this.limitMotor2.axis.x;
- this.ay2 = this.limitMotor2.axis.y;
- this.az2 = this.limitMotor2.axis.z;
- this.ax3 = this.limitMotor3.axis.x;
- this.ay3 = this.limitMotor3.axis.y;
- this.az3 = this.limitMotor3.axis.z;
- this.lowerLimit1 = this.limitMotor1.lowerLimit;
- this.upperLimit1 = this.limitMotor1.upperLimit;
- this.motorSpeed1 = this.limitMotor1.motorSpeed;
- this.maxMotorForce1 = this.limitMotor1.maxMotorForce;
- this.enableMotor1 = this.maxMotorForce1 > 0;
- this.lowerLimit2 = this.limitMotor2.lowerLimit;
- this.upperLimit2 = this.limitMotor2.upperLimit;
- this.motorSpeed2 = this.limitMotor2.motorSpeed;
- this.maxMotorForce2 = this.limitMotor2.maxMotorForce;
- this.enableMotor2 = this.maxMotorForce2 > 0;
- this.lowerLimit3 = this.limitMotor3.lowerLimit;
- this.upperLimit3 = this.limitMotor3.upperLimit;
- this.motorSpeed3 = this.limitMotor3.motorSpeed;
- this.maxMotorForce3 = this.limitMotor3.maxMotorForce;
- this.enableMotor3 = this.maxMotorForce3 > 0;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var dx = this.p2.x - this.p1.x;
- var dy = this.p2.y - this.p1.y;
- var dz = this.p2.z - this.p1.z;
- var d1 = dx * this.ax1 + dy * this.ay1 + dz * this.az1;
- var d2 = dx * this.ax2 + dy * this.ay2 + dz * this.az2;
- var d3 = dx * this.ax3 + dy * this.ay3 + dz * this.az3;
- var frequency1 = this.limitMotor1.frequency;
- var frequency2 = this.limitMotor2.frequency;
- var frequency3 = this.limitMotor3.frequency;
- var enableSpring1 = frequency1 > 0;
- var enableSpring2 = frequency2 > 0;
- var enableSpring3 = frequency3 > 0;
- var enableLimit1 = this.lowerLimit1 <= this.upperLimit1;
- var enableLimit2 = this.lowerLimit2 <= this.upperLimit2;
- var enableLimit3 = this.lowerLimit3 <= this.upperLimit3;
- // for stability
- if (enableSpring1 && d1 > 20 || d1 < -20) {
- enableSpring1 = false;
- }
- if (enableSpring2 && d2 > 20 || d2 < -20) {
- enableSpring2 = false;
- }
- if (enableSpring3 && d3 > 20 || d3 < -20) {
- enableSpring3 = false;
- }
- if (enableLimit1) {
- if (this.lowerLimit1 == this.upperLimit1) {
- if (this.limitState1 != 0) {
- this.limitState1 = 0;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - d1;
- if (!enableSpring1) d1 = this.lowerLimit1;
- } else if (d1 < this.lowerLimit1) {
- if (this.limitState1 != -1) {
- this.limitState1 = -1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.lowerLimit1 - d1;
- if (!enableSpring1) d1 = this.lowerLimit1;
- } else if (d1 > this.upperLimit1) {
- if (this.limitState1 != 1) {
- this.limitState1 = 1;
- this.limitImpulse1 = 0;
- }
- this.limitVelocity1 = this.upperLimit1 - d1;
- if (!enableSpring1) d1 = this.upperLimit1;
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- this.limitVelocity1 = 0;
- }
- if (!enableSpring1) {
- if (this.limitVelocity1 > 0.005) this.limitVelocity1 -= 0.005;
- else if (this.limitVelocity1 < -0.005) this.limitVelocity1 += 0.005;
- else this.limitVelocity1 = 0;
- }
- } else {
- this.limitState1 = 2;
- this.limitImpulse1 = 0;
- }
- if (enableLimit2) {
- if (this.lowerLimit2 == this.upperLimit2) {
- if (this.limitState2 != 0) {
- this.limitState2 = 0;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - d2;
- if (!enableSpring2) d2 = this.lowerLimit2;
- } else if (d2 < this.lowerLimit2) {
- if (this.limitState2 != -1) {
- this.limitState2 = -1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.lowerLimit2 - d2;
- if (!enableSpring2) d2 = this.lowerLimit2;
- } else if (d2 > this.upperLimit2) {
- if (this.limitState2 != 1) {
- this.limitState2 = 1;
- this.limitImpulse2 = 0;
- }
- this.limitVelocity2 = this.upperLimit2 - d2;
- if (!enableSpring2) d2 = this.upperLimit2;
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- this.limitVelocity2 = 0;
- }
- if (!enableSpring2) {
- if (this.limitVelocity2 > 0.005) this.limitVelocity2 -= 0.005;
- else if (this.limitVelocity2 < -0.005) this.limitVelocity2 += 0.005;
- else this.limitVelocity2 = 0;
- }
- } else {
- this.limitState2 = 2;
- this.limitImpulse2 = 0;
- }
- if (enableLimit3) {
- if (this.lowerLimit3 == this.upperLimit3) {
- if (this.limitState3 != 0) {
- this.limitState3 = 0;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - d3;
- if (!enableSpring3) d3 = this.lowerLimit3;
- } else if (d3 < this.lowerLimit3) {
- if (this.limitState3 != -1) {
- this.limitState3 = -1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.lowerLimit3 - d3;
- if (!enableSpring3) d3 = this.lowerLimit3;
- } else if (d3 > this.upperLimit3) {
- if (this.limitState3 != 1) {
- this.limitState3 = 1;
- this.limitImpulse3 = 0;
- }
- this.limitVelocity3 = this.upperLimit3 - d3;
- if (!enableSpring3) d3 = this.upperLimit3;
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- this.limitVelocity3 = 0;
- }
- if (!enableSpring3) {
- if (this.limitVelocity3 > 0.005) this.limitVelocity3 -= 0.005;
- else if (this.limitVelocity3 < -0.005) this.limitVelocity3 += 0.005;
- else this.limitVelocity3 = 0;
- }
- } else {
- this.limitState3 = 2;
- this.limitImpulse3 = 0;
- }
- if (this.enableMotor1 && (this.limitState1 != 0 || enableSpring1)) {
- this.maxMotorImpulse1 = this.maxMotorForce1 * timeStep;
- } else {
- this.motorImpulse1 = 0;
- this.maxMotorImpulse1 = 0;
- }
- if (this.enableMotor2 && (this.limitState2 != 0 || enableSpring2)) {
- this.maxMotorImpulse2 = this.maxMotorForce2 * timeStep;
- } else {
- this.motorImpulse2 = 0;
- this.maxMotorImpulse2 = 0;
- }
- if (this.enableMotor3 && (this.limitState3 != 0 || enableSpring3)) {
- this.maxMotorImpulse3 = this.maxMotorForce3 * timeStep;
- } else {
- this.motorImpulse3 = 0;
- this.maxMotorImpulse3 = 0;
- }
- var rdx = d1 * this.ax1 + d2 * this.ax2 + d3 * this.ax2;
- var rdy = d1 * this.ay1 + d2 * this.ay2 + d3 * this.ay2;
- var rdz = d1 * this.az1 + d2 * this.az2 + d3 * this.az2;
- var w1 = this.m2 / (this.m1 + this.m2);
- if (this.weight >= 0) w1 = this.weight; // use given weight
- var w2 = 1 - w1;
- this.r1x = this.r1.x + rdx * w1;
- this.r1y = this.r1.y + rdy * w1;
- this.r1z = this.r1.z + rdz * w1;
- this.r2x = this.r2.x - rdx * w2;
- this.r2y = this.r2.y - rdy * w2;
- this.r2z = this.r2.z - rdz * w2;
- // build jacobians
- this.t1x1 = this.r1y * this.az1 - this.r1z * this.ay1;
- this.t1y1 = this.r1z * this.ax1 - this.r1x * this.az1;
- this.t1z1 = this.r1x * this.ay1 - this.r1y * this.ax1;
- this.t2x1 = this.r2y * this.az1 - this.r2z * this.ay1;
- this.t2y1 = this.r2z * this.ax1 - this.r2x * this.az1;
- this.t2z1 = this.r2x * this.ay1 - this.r2y * this.ax1;
- this.l1x1 = this.ax1 * this.m1;
- this.l1y1 = this.ay1 * this.m1;
- this.l1z1 = this.az1 * this.m1;
- this.l2x1 = this.ax1 * this.m2;
- this.l2y1 = this.ay1 * this.m2;
- this.l2z1 = this.az1 * this.m2;
- this.a1x1 = this.t1x1 * this.i1e00 + this.t1y1 * this.i1e01 + this.t1z1 * this.i1e02;
- this.a1y1 = this.t1x1 * this.i1e10 + this.t1y1 * this.i1e11 + this.t1z1 * this.i1e12;
- this.a1z1 = this.t1x1 * this.i1e20 + this.t1y1 * this.i1e21 + this.t1z1 * this.i1e22;
- this.a2x1 = this.t2x1 * this.i2e00 + this.t2y1 * this.i2e01 + this.t2z1 * this.i2e02;
- this.a2y1 = this.t2x1 * this.i2e10 + this.t2y1 * this.i2e11 + this.t2z1 * this.i2e12;
- this.a2z1 = this.t2x1 * this.i2e20 + this.t2y1 * this.i2e21 + this.t2z1 * this.i2e22;
- this.t1x2 = this.r1y * this.az2 - this.r1z * this.ay2;
- this.t1y2 = this.r1z * this.ax2 - this.r1x * this.az2;
- this.t1z2 = this.r1x * this.ay2 - this.r1y * this.ax2;
- this.t2x2 = this.r2y * this.az2 - this.r2z * this.ay2;
- this.t2y2 = this.r2z * this.ax2 - this.r2x * this.az2;
- this.t2z2 = this.r2x * this.ay2 - this.r2y * this.ax2;
- this.l1x2 = this.ax2 * this.m1;
- this.l1y2 = this.ay2 * this.m1;
- this.l1z2 = this.az2 * this.m1;
- this.l2x2 = this.ax2 * this.m2;
- this.l2y2 = this.ay2 * this.m2;
- this.l2z2 = this.az2 * this.m2;
- this.a1x2 = this.t1x2 * this.i1e00 + this.t1y2 * this.i1e01 + this.t1z2 * this.i1e02;
- this.a1y2 = this.t1x2 * this.i1e10 + this.t1y2 * this.i1e11 + this.t1z2 * this.i1e12;
- this.a1z2 = this.t1x2 * this.i1e20 + this.t1y2 * this.i1e21 + this.t1z2 * this.i1e22;
- this.a2x2 = this.t2x2 * this.i2e00 + this.t2y2 * this.i2e01 + this.t2z2 * this.i2e02;
- this.a2y2 = this.t2x2 * this.i2e10 + this.t2y2 * this.i2e11 + this.t2z2 * this.i2e12;
- this.a2z2 = this.t2x2 * this.i2e20 + this.t2y2 * this.i2e21 + this.t2z2 * this.i2e22;
- this.t1x3 = this.r1y * this.az3 - this.r1z * this.ay3;
- this.t1y3 = this.r1z * this.ax3 - this.r1x * this.az3;
- this.t1z3 = this.r1x * this.ay3 - this.r1y * this.ax3;
- this.t2x3 = this.r2y * this.az3 - this.r2z * this.ay3;
- this.t2y3 = this.r2z * this.ax3 - this.r2x * this.az3;
- this.t2z3 = this.r2x * this.ay3 - this.r2y * this.ax3;
- this.l1x3 = this.ax3 * this.m1;
- this.l1y3 = this.ay3 * this.m1;
- this.l1z3 = this.az3 * this.m1;
- this.l2x3 = this.ax3 * this.m2;
- this.l2y3 = this.ay3 * this.m2;
- this.l2z3 = this.az3 * this.m2;
- this.a1x3 = this.t1x3 * this.i1e00 + this.t1y3 * this.i1e01 + this.t1z3 * this.i1e02;
- this.a1y3 = this.t1x3 * this.i1e10 + this.t1y3 * this.i1e11 + this.t1z3 * this.i1e12;
- this.a1z3 = this.t1x3 * this.i1e20 + this.t1y3 * this.i1e21 + this.t1z3 * this.i1e22;
- this.a2x3 = this.t2x3 * this.i2e00 + this.t2y3 * this.i2e01 + this.t2z3 * this.i2e02;
- this.a2y3 = this.t2x3 * this.i2e10 + this.t2y3 * this.i2e11 + this.t2z3 * this.i2e12;
- this.a2z3 = this.t2x3 * this.i2e20 + this.t2y3 * this.i2e21 + this.t2z3 * this.i2e22;
- // build an impulse matrix
- var m12 = this.m1 + this.m2;
- this.k00 = (this.ax1 * this.ax1 + this.ay1 * this.ay1 + this.az1 * this.az1) * m12;
- this.k01 = (this.ax1 * this.ax2 + this.ay1 * this.ay2 + this.az1 * this.az2) * m12;
- this.k02 = (this.ax1 * this.ax3 + this.ay1 * this.ay3 + this.az1 * this.az3) * m12;
- this.k10 = (this.ax2 * this.ax1 + this.ay2 * this.ay1 + this.az2 * this.az1) * m12;
- this.k11 = (this.ax2 * this.ax2 + this.ay2 * this.ay2 + this.az2 * this.az2) * m12;
- this.k12 = (this.ax2 * this.ax3 + this.ay2 * this.ay3 + this.az2 * this.az3) * m12;
- this.k20 = (this.ax3 * this.ax1 + this.ay3 * this.ay1 + this.az3 * this.az1) * m12;
- this.k21 = (this.ax3 * this.ax2 + this.ay3 * this.ay2 + this.az3 * this.az2) * m12;
- this.k22 = (this.ax3 * this.ax3 + this.ay3 * this.ay3 + this.az3 * this.az3) * m12;
- this.k00 += this.t1x1 * this.a1x1 + this.t1y1 * this.a1y1 + this.t1z1 * this.a1z1;
- this.k01 += this.t1x1 * this.a1x2 + this.t1y1 * this.a1y2 + this.t1z1 * this.a1z2;
- this.k02 += this.t1x1 * this.a1x3 + this.t1y1 * this.a1y3 + this.t1z1 * this.a1z3;
- this.k10 += this.t1x2 * this.a1x1 + this.t1y2 * this.a1y1 + this.t1z2 * this.a1z1;
- this.k11 += this.t1x2 * this.a1x2 + this.t1y2 * this.a1y2 + this.t1z2 * this.a1z2;
- this.k12 += this.t1x2 * this.a1x3 + this.t1y2 * this.a1y3 + this.t1z2 * this.a1z3;
- this.k20 += this.t1x3 * this.a1x1 + this.t1y3 * this.a1y1 + this.t1z3 * this.a1z1;
- this.k21 += this.t1x3 * this.a1x2 + this.t1y3 * this.a1y2 + this.t1z3 * this.a1z2;
- this.k22 += this.t1x3 * this.a1x3 + this.t1y3 * this.a1y3 + this.t1z3 * this.a1z3;
- this.k00 += this.t2x1 * this.a2x1 + this.t2y1 * this.a2y1 + this.t2z1 * this.a2z1;
- this.k01 += this.t2x1 * this.a2x2 + this.t2y1 * this.a2y2 + this.t2z1 * this.a2z2;
- this.k02 += this.t2x1 * this.a2x3 + this.t2y1 * this.a2y3 + this.t2z1 * this.a2z3;
- this.k10 += this.t2x2 * this.a2x1 + this.t2y2 * this.a2y1 + this.t2z2 * this.a2z1;
- this.k11 += this.t2x2 * this.a2x2 + this.t2y2 * this.a2y2 + this.t2z2 * this.a2z2;
- this.k12 += this.t2x2 * this.a2x3 + this.t2y2 * this.a2y3 + this.t2z2 * this.a2z3;
- this.k20 += this.t2x3 * this.a2x1 + this.t2y3 * this.a2y1 + this.t2z3 * this.a2z1;
- this.k21 += this.t2x3 * this.a2x2 + this.t2y3 * this.a2y2 + this.t2z3 * this.a2z2;
- this.k22 += this.t2x3 * this.a2x3 + this.t2y3 * this.a2y3 + this.t2z3 * this.a2z3;
- this.kv00 = this.k00;
- this.kv11 = this.k11;
- this.kv22 = this.k22;
- this.dv00 = 1 / this.kv00;
- this.dv11 = 1 / this.kv11;
- this.dv22 = 1 / this.kv22;
- if (enableSpring1 && this.limitState1 != 2) {
- var omega = 6.2831853 * frequency1;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor1.dampingRatio * omega);
- this.cfm1 = this.kv00 * dmp;
- this.limitVelocity1 *= k * dmp;
- } else {
- this.cfm1 = 0;
- this.limitVelocity1 *= invTimeStep * 0.05;
- }
- if (enableSpring2 && this.limitState2 != 2) {
- omega = 6.2831853 * frequency2;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor2.dampingRatio * omega);
- this.cfm2 = this.kv11 * dmp;
- this.limitVelocity2 *= k * dmp;
- } else {
- this.cfm2 = 0;
- this.limitVelocity2 *= invTimeStep * 0.05;
- }
- if (enableSpring3 && this.limitState3 != 2) {
- omega = 6.2831853 * frequency3;
- k = omega * omega * timeStep;
- dmp = invTimeStep / (k + 2 * this.limitMotor3.dampingRatio * omega);
- this.cfm3 = this.kv22 * dmp;
- this.limitVelocity3 *= k * dmp;
- } else {
- this.cfm3 = 0;
- this.limitVelocity3 *= invTimeStep * 0.05;
- }
- this.k00 += this.cfm1;
- this.k11 += this.cfm2;
- this.k22 += this.cfm3;
- var inv = 1 / (
- this.k00 * (this.k11 * this.k22 - this.k21 * this.k12) +
- this.k10 * (this.k21 * this.k02 - this.k01 * this.k22) +
- this.k20 * (this.k01 * this.k12 - this.k11 * this.k02)
- );
- this.d00 = (this.k11 * this.k22 - this.k12 * this.k21) * inv;
- this.d01 = (this.k02 * this.k21 - this.k01 * this.k22) * inv;
- this.d02 = (this.k01 * this.k12 - this.k02 * this.k11) * inv;
- this.d10 = (this.k12 * this.k20 - this.k10 * this.k22) * inv;
- this.d11 = (this.k00 * this.k22 - this.k02 * this.k20) * inv;
- this.d12 = (this.k02 * this.k10 - this.k00 * this.k12) * inv;
- this.d20 = (this.k10 * this.k21 - this.k11 * this.k20) * inv;
- this.d21 = (this.k01 * this.k20 - this.k00 * this.k21) * inv;
- this.d22 = (this.k00 * this.k11 - this.k01 * this.k10) * inv;
- // warm starting
- var totalImpulse1 = this.limitImpulse1 + this.motorImpulse1;
- var totalImpulse2 = this.limitImpulse2 + this.motorImpulse2;
- var totalImpulse3 = this.limitImpulse3 + this.motorImpulse3;
- this.l1.x += totalImpulse1 * this.l1x1 + totalImpulse2 * this.l1x2 + totalImpulse3 * this.l1x3;
- this.l1.y += totalImpulse1 * this.l1y1 + totalImpulse2 * this.l1y2 + totalImpulse3 * this.l1y3;
- this.l1.z += totalImpulse1 * this.l1z1 + totalImpulse2 * this.l1z2 + totalImpulse3 * this.l1z3;
- this.a1.x += totalImpulse1 * this.a1x1 + totalImpulse2 * this.a1x2 + totalImpulse3 * this.a1x3;
- this.a1.y += totalImpulse1 * this.a1y1 + totalImpulse2 * this.a1y2 + totalImpulse3 * this.a1y3;
- this.a1.z += totalImpulse1 * this.a1z1 + totalImpulse2 * this.a1z2 + totalImpulse3 * this.a1z3;
- this.l2.x -= totalImpulse1 * this.l2x1 + totalImpulse2 * this.l2x2 + totalImpulse3 * this.l2x3;
- this.l2.y -= totalImpulse1 * this.l2y1 + totalImpulse2 * this.l2y2 + totalImpulse3 * this.l2y3;
- this.l2.z -= totalImpulse1 * this.l2z1 + totalImpulse2 * this.l2z2 + totalImpulse3 * this.l2z3;
- this.a2.x -= totalImpulse1 * this.a2x1 + totalImpulse2 * this.a2x2 + totalImpulse3 * this.a2x3;
- this.a2.y -= totalImpulse1 * this.a2y1 + totalImpulse2 * this.a2y2 + totalImpulse3 * this.a2y3;
- this.a2.z -= totalImpulse1 * this.a2z1 + totalImpulse2 * this.a2z2 + totalImpulse3 * this.a2z3;
- },
- solve: function () {
- var rvx = this.l2.x - this.l1.x + this.a2.y * this.r2z - this.a2.z * this.r2y - this.a1.y * this.r1z + this.a1.z * this.r1y;
- var rvy = this.l2.y - this.l1.y + this.a2.z * this.r2x - this.a2.x * this.r2z - this.a1.z * this.r1x + this.a1.x * this.r1z;
- var rvz = this.l2.z - this.l1.z + this.a2.x * this.r2y - this.a2.y * this.r2x - this.a1.x * this.r1y + this.a1.y * this.r1x;
- var rvn1 = rvx * this.ax1 + rvy * this.ay1 + rvz * this.az1;
- var rvn2 = rvx * this.ax2 + rvy * this.ay2 + rvz * this.az2;
- var rvn3 = rvx * this.ax3 + rvy * this.ay3 + rvz * this.az3;
- var oldMotorImpulse1 = this.motorImpulse1;
- var oldMotorImpulse2 = this.motorImpulse2;
- var oldMotorImpulse3 = this.motorImpulse3;
- var dMotorImpulse1 = 0;
- var dMotorImpulse2 = 0;
- var dMotorImpulse3 = 0;
- if (this.enableMotor1) {
- dMotorImpulse1 = (rvn1 - this.motorSpeed1) * this.dv00;
- this.motorImpulse1 += dMotorImpulse1;
- if (this.motorImpulse1 > this.maxMotorImpulse1) { // clamp motor impulse
- this.motorImpulse1 = this.maxMotorImpulse1;
- } else if (this.motorImpulse1 < -this.maxMotorImpulse1) {
- this.motorImpulse1 = -this.maxMotorImpulse1;
- }
- dMotorImpulse1 = this.motorImpulse1 - oldMotorImpulse1;
- }
- if (this.enableMotor2) {
- dMotorImpulse2 = (rvn2 - this.motorSpeed2) * this.dv11;
- this.motorImpulse2 += dMotorImpulse2;
- if (this.motorImpulse2 > this.maxMotorImpulse2) { // clamp motor impulse
- this.motorImpulse2 = this.maxMotorImpulse2;
- } else if (this.motorImpulse2 < -this.maxMotorImpulse2) {
- this.motorImpulse2 = -this.maxMotorImpulse2;
- }
- dMotorImpulse2 = this.motorImpulse2 - oldMotorImpulse2;
- }
- if (this.enableMotor3) {
- dMotorImpulse3 = (rvn3 - this.motorSpeed3) * this.dv22;
- this.motorImpulse3 += dMotorImpulse3;
- if (this.motorImpulse3 > this.maxMotorImpulse3) { // clamp motor impulse
- this.motorImpulse3 = this.maxMotorImpulse3;
- } else if (this.motorImpulse3 < -this.maxMotorImpulse3) {
- this.motorImpulse3 = -this.maxMotorImpulse3;
- }
- dMotorImpulse3 = this.motorImpulse3 - oldMotorImpulse3;
- }
- // apply motor impulse to relative velocity
- rvn1 += dMotorImpulse1 * this.kv00 + dMotorImpulse2 * this.k01 + dMotorImpulse3 * this.k02;
- rvn2 += dMotorImpulse1 * this.k10 + dMotorImpulse2 * this.kv11 + dMotorImpulse3 * this.k12;
- rvn3 += dMotorImpulse1 * this.k20 + dMotorImpulse2 * this.k21 + dMotorImpulse3 * this.kv22;
- // subtract target velocity and applied impulse
- rvn1 -= this.limitVelocity1 + this.limitImpulse1 * this.cfm1;
- rvn2 -= this.limitVelocity2 + this.limitImpulse2 * this.cfm2;
- rvn3 -= this.limitVelocity3 + this.limitImpulse3 * this.cfm3;
- var oldLimitImpulse1 = this.limitImpulse1;
- var oldLimitImpulse2 = this.limitImpulse2;
- var oldLimitImpulse3 = this.limitImpulse3;
- var dLimitImpulse1 = rvn1 * this.d00 + rvn2 * this.d01 + rvn3 * this.d02;
- var dLimitImpulse2 = rvn1 * this.d10 + rvn2 * this.d11 + rvn3 * this.d12;
- var dLimitImpulse3 = rvn1 * this.d20 + rvn2 * this.d21 + rvn3 * this.d22;
- this.limitImpulse1 += dLimitImpulse1;
- this.limitImpulse2 += dLimitImpulse2;
- this.limitImpulse3 += dLimitImpulse3;
- // clamp
- var clampState = 0;
- if (this.limitState1 == 2 || this.limitImpulse1 * this.limitState1 < 0) {
- dLimitImpulse1 = -oldLimitImpulse1;
- rvn2 += dLimitImpulse1 * this.k10;
- rvn3 += dLimitImpulse1 * this.k20;
- clampState |= 1;
- }
- if (this.limitState2 == 2 || this.limitImpulse2 * this.limitState2 < 0) {
- dLimitImpulse2 = -oldLimitImpulse2;
- rvn1 += dLimitImpulse2 * this.k01;
- rvn3 += dLimitImpulse2 * this.k21;
- clampState |= 2;
- }
- if (this.limitState3 == 2 || this.limitImpulse3 * this.limitState3 < 0) {
- dLimitImpulse3 = -oldLimitImpulse3;
- rvn1 += dLimitImpulse3 * this.k02;
- rvn2 += dLimitImpulse3 * this.k12;
- clampState |= 4;
- }
- // update un-clamped impulse
- // TODO: isolate division
- var det;
- switch (clampState) {
- case 1:// update 2 3
- det = 1 / (this.k11 * this.k22 - this.k12 * this.k21);
- dLimitImpulse2 = (this.k22 * rvn2 + -this.k12 * rvn3) * det;
- dLimitImpulse3 = (-this.k21 * rvn2 + this.k11 * rvn3) * det;
- break;
- case 2:// update 1 3
- det = 1 / (this.k00 * this.k22 - this.k02 * this.k20);
- dLimitImpulse1 = (this.k22 * rvn1 + -this.k02 * rvn3) * det;
- dLimitImpulse3 = (-this.k20 * rvn1 + this.k00 * rvn3) * det;
- break;
- case 3:// update 3
- dLimitImpulse3 = rvn3 / this.k22;
- break;
- case 4:// update 1 2
- det = 1 / (this.k00 * this.k11 - this.k01 * this.k10);
- dLimitImpulse1 = (this.k11 * rvn1 + -this.k01 * rvn2) * det;
- dLimitImpulse2 = (-this.k10 * rvn1 + this.k00 * rvn2) * det;
- break;
- case 5:// update 2
- dLimitImpulse2 = rvn2 / this.k11;
- break;
- case 6:// update 1
- dLimitImpulse1 = rvn1 / this.k00;
- break;
- }
- this.limitImpulse1 = oldLimitImpulse1 + dLimitImpulse1;
- this.limitImpulse2 = oldLimitImpulse2 + dLimitImpulse2;
- this.limitImpulse3 = oldLimitImpulse3 + dLimitImpulse3;
- var dImpulse1 = dMotorImpulse1 + dLimitImpulse1;
- var dImpulse2 = dMotorImpulse2 + dLimitImpulse2;
- var dImpulse3 = dMotorImpulse3 + dLimitImpulse3;
- // apply impulse
- this.l1.x += dImpulse1 * this.l1x1 + dImpulse2 * this.l1x2 + dImpulse3 * this.l1x3;
- this.l1.y += dImpulse1 * this.l1y1 + dImpulse2 * this.l1y2 + dImpulse3 * this.l1y3;
- this.l1.z += dImpulse1 * this.l1z1 + dImpulse2 * this.l1z2 + dImpulse3 * this.l1z3;
- this.a1.x += dImpulse1 * this.a1x1 + dImpulse2 * this.a1x2 + dImpulse3 * this.a1x3;
- this.a1.y += dImpulse1 * this.a1y1 + dImpulse2 * this.a1y2 + dImpulse3 * this.a1y3;
- this.a1.z += dImpulse1 * this.a1z1 + dImpulse2 * this.a1z2 + dImpulse3 * this.a1z3;
- this.l2.x -= dImpulse1 * this.l2x1 + dImpulse2 * this.l2x2 + dImpulse3 * this.l2x3;
- this.l2.y -= dImpulse1 * this.l2y1 + dImpulse2 * this.l2y2 + dImpulse3 * this.l2y3;
- this.l2.z -= dImpulse1 * this.l2z1 + dImpulse2 * this.l2z2 + dImpulse3 * this.l2z3;
- this.a2.x -= dImpulse1 * this.a2x1 + dImpulse2 * this.a2x2 + dImpulse3 * this.a2x3;
- this.a2.y -= dImpulse1 * this.a2y1 + dImpulse2 * this.a2y2 + dImpulse3 * this.a2y3;
- this.a2.z -= dImpulse1 * this.a2z1 + dImpulse2 * this.a2z2 + dImpulse3 * this.a2z3;
- }
- }
- /**
- * A translational constraint for various joints.
- * @author saharan
- */
- OIMO.TranslationalConstraint = function (joint, limitMotor) {
- this.cfm = NaN;
- this.m1 = NaN;
- this.m2 = NaN;
- this.i1e00 = NaN;
- this.i1e01 = NaN;
- this.i1e02 = NaN;
- this.i1e10 = NaN;
- this.i1e11 = NaN;
- this.i1e12 = NaN;
- this.i1e20 = NaN;
- this.i1e21 = NaN;
- this.i1e22 = NaN;
- this.i2e00 = NaN;
- this.i2e01 = NaN;
- this.i2e02 = NaN;
- this.i2e10 = NaN;
- this.i2e11 = NaN;
- this.i2e12 = NaN;
- this.i2e20 = NaN;
- this.i2e21 = NaN;
- this.i2e22 = NaN;
- this.motorDenom = NaN;
- this.invMotorDenom = NaN;
- this.invDenom = NaN;
- this.ax = NaN;
- this.ay = NaN;
- this.az = NaN;
- this.r1x = NaN;
- this.r1y = NaN;
- this.r1z = NaN;
- this.r2x = NaN;
- this.r2y = NaN;
- this.r2z = NaN;
- this.t1x = NaN;
- this.t1y = NaN;
- this.t1z = NaN;
- this.t2x = NaN;
- this.t2y = NaN;
- this.t2z = NaN;
- this.l1x = NaN;
- this.l1y = NaN;
- this.l1z = NaN;
- this.l2x = NaN;
- this.l2y = NaN;
- this.l2z = NaN;
- this.a1x = NaN;
- this.a1y = NaN;
- this.a1z = NaN;
- this.a2x = NaN;
- this.a2y = NaN;
- this.a2z = NaN;
- this.lowerLimit = NaN;
- this.upperLimit = NaN;
- this.limitVelocity = NaN;
- this.limitState = 0; // -1: at lower, 0: locked, 1: at upper, 2: free
- this.enableMotor = false;
- this.motorSpeed = NaN;
- this.maxMotorForce = NaN;
- this.maxMotorImpulse = NaN;
- this.limitMotor = limitMotor;
- this.b1 = joint.body1;
- this.b2 = joint.body2;
- this.p1 = joint.anchorPoint1;
- this.p2 = joint.anchorPoint2;
- this.r1 = joint.relativeAnchorPoint1;
- this.r2 = joint.relativeAnchorPoint2;
- this.l1 = this.b1.linearVelocity;
- this.l2 = this.b2.linearVelocity;
- this.a1 = this.b1.angularVelocity;
- this.a2 = this.b2.angularVelocity;
- this.i1 = this.b1.inverseInertia;
- this.i2 = this.b2.inverseInertia;
- this.limitImpulse = 0;
- this.motorImpulse = 0;
- }
- OIMO.TranslationalConstraint.prototype = {
- constructor: OIMO.TranslationalConstraint,
- preSolve: function (timeStep, invTimeStep) {
- this.ax = this.limitMotor.axis.x;
- this.ay = this.limitMotor.axis.y;
- this.az = this.limitMotor.axis.z;
- this.lowerLimit = this.limitMotor.lowerLimit;
- this.upperLimit = this.limitMotor.upperLimit;
- this.motorSpeed = this.limitMotor.motorSpeed;
- this.maxMotorForce = this.limitMotor.maxMotorForce;
- this.enableMotor = this.maxMotorForce > 0;
- this.m1 = this.b1.inverseMass;
- this.m2 = this.b2.inverseMass;
- var ti1 = this.i1.elements;
- var ti2 = this.i2.elements;
- this.i1e00 = ti1[0];
- this.i1e01 = ti1[1];
- this.i1e02 = ti1[2];
- this.i1e10 = ti1[3];
- this.i1e11 = ti1[4];
- this.i1e12 = ti1[5];
- this.i1e20 = ti1[6];
- this.i1e21 = ti1[7];
- this.i1e22 = ti1[8];
- this.i2e00 = ti2[0];
- this.i2e01 = ti2[1];
- this.i2e02 = ti2[2];
- this.i2e10 = ti2[3];
- this.i2e11 = ti2[4];
- this.i2e12 = ti2[5];
- this.i2e20 = ti2[6];
- this.i2e21 = ti2[7];
- this.i2e22 = ti2[8];
- var dx = this.p2.x - this.p1.x;
- var dy = this.p2.y - this.p1.y;
- var dz = this.p2.z - this.p1.z;
- var d = dx * this.ax + dy * this.ay + dz * this.az;
- var frequency = this.limitMotor.frequency;
- var enableSpring = frequency > 0;
- var enableLimit = this.lowerLimit <= this.upperLimit;
- if (enableSpring && d > 20 || d < -20) {
- enableSpring = false;
- }
- if (enableLimit) {
- if (this.lowerLimit == this.upperLimit) {
- if (this.limitState != 0) {
- this.limitState = 0;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - d;
- if (!enableSpring) d = this.lowerLimit;
- } else if (d < this.lowerLimit) {
- if (this.limitState != -1) {
- this.limitState = -1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.lowerLimit - d;
- if (!enableSpring) d = this.lowerLimit;
- } else if (d > this.upperLimit) {
- if (this.limitState != 1) {
- this.limitState = 1;
- this.limitImpulse = 0;
- }
- this.limitVelocity = this.upperLimit - d;
- if (!enableSpring) d = this.upperLimit;
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- this.limitVelocity = 0;
- }
- if (!enableSpring) {
- if (this.limitVelocity > 0.005) this.limitVelocity -= 0.005;
- else if (this.limitVelocity < -0.005) this.limitVelocity += 0.005;
- else this.limitVelocity = 0;
- }
- } else {
- this.limitState = 2;
- this.limitImpulse = 0;
- }
- if (this.enableMotor && (this.limitState != 0 || enableSpring)) {
- this.maxMotorImpulse = this.maxMotorForce * timeStep;
- } else {
- this.motorImpulse = 0;
- this.maxMotorImpulse = 0;
- }
- var rdx = d * this.ax;
- var rdy = d * this.ay;
- var rdz = d * this.az;
- var w1 = this.m1 / (this.m1 + this.m2);
- var w2 = 1 - w1;
- this.r1x = this.r1.x + rdx * w1;
- this.r1y = this.r1.y + rdy * w1;
- this.r1z = this.r1.z + rdz * w1;
- this.r2x = this.r2.x - rdx * w2;
- this.r2y = this.r2.y - rdy * w2;
- this.r2z = this.r2.z - rdz * w2;
- this.t1x = this.r1y * this.az - this.r1z * this.ay;
- this.t1y = this.r1z * this.ax - this.r1x * this.az;
- this.t1z = this.r1x * this.ay - this.r1y * this.ax;
- this.t2x = this.r2y * this.az - this.r2z * this.ay;
- this.t2y = this.r2z * this.ax - this.r2x * this.az;
- this.t2z = this.r2x * this.ay - this.r2y * this.ax;
- this.l1x = this.ax * this.m1;
- this.l1y = this.ay * this.m1;
- this.l1z = this.az * this.m1;
- this.l2x = this.ax * this.m2;
- this.l2y = this.ay * this.m2;
- this.l2z = this.az * this.m2;
- this.a1x = this.t1x * this.i1e00 + this.t1y * this.i1e01 + this.t1z * this.i1e02;
- this.a1y = this.t1x * this.i1e10 + this.t1y * this.i1e11 + this.t1z * this.i1e12;
- this.a1z = this.t1x * this.i1e20 + this.t1y * this.i1e21 + this.t1z * this.i1e22;
- this.a2x = this.t2x * this.i2e00 + this.t2y * this.i2e01 + this.t2z * this.i2e02;
- this.a2y = this.t2x * this.i2e10 + this.t2y * this.i2e11 + this.t2z * this.i2e12;
- this.a2z = this.t2x * this.i2e20 + this.t2y * this.i2e21 + this.t2z * this.i2e22;
- this.motorDenom =
- this.m1 + this.m2 +
- this.ax * (this.a1y * this.r1z - this.a1z * this.r1y + this.a2y * this.r2z - this.a2z * this.r2y) +
- this.ay * (this.a1z * this.r1x - this.a1x * this.r1z + this.a2z * this.r2x - this.a2x * this.r2z) +
- this.az * (this.a1x * this.r1y - this.a1y * this.r1x + this.a2x * this.r2y - this.a2y * this.r2x);
- this.invMotorDenom = 1 / this.motorDenom;
- if (enableSpring && this.limitState != 2) {
- var omega = 6.2831853 * frequency;
- var k = omega * omega * timeStep;
- var dmp = invTimeStep / (k + 2 * this.limitMotor.dampingRatio * omega);
- this.cfm = this.motorDenom * dmp;
- this.limitVelocity *= k * dmp;
- } else {
- this.cfm = 0;
- this.limitVelocity *= invTimeStep * 0.05;
- }
- this.invDenom = 1 / (this.motorDenom + this.cfm);
- var totalImpulse = this.limitImpulse + this.motorImpulse;
- this.l1.x += totalImpulse * this.l1x;
- this.l1.y += totalImpulse * this.l1y;
- this.l1.z += totalImpulse * this.l1z;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.l2.x -= totalImpulse * this.l2x;
- this.l2.y -= totalImpulse * this.l2y;
- this.l2.z -= totalImpulse * this.l2z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- },
- solve: function () {
- var rvn =
- this.ax * (this.l2.x - this.l1.x) + this.ay * (this.l2.y - this.l1.y) + this.az * (this.l2.z - this.l1.z) +
- this.t2x * this.a2.x - this.t1x * this.a1.x + this.t2y * this.a2.y - this.t1y * this.a1.y + this.t2z * this.a2.z - this.t1z * this.a1.z;
- // motor part
- var newMotorImpulse;
- if (this.enableMotor) {
- newMotorImpulse = (rvn - this.motorSpeed) * this.invMotorDenom;
- var oldMotorImpulse = this.motorImpulse;
- this.motorImpulse += newMotorImpulse;
- if (this.motorImpulse > this.maxMotorImpulse) this.motorImpulse = this.maxMotorImpulse;
- else if (this.motorImpulse < -this.maxMotorImpulse) this.motorImpulse = -this.maxMotorImpulse;
- newMotorImpulse = this.motorImpulse - oldMotorImpulse;
- rvn -= newMotorImpulse * this.motorDenom;
- } else newMotorImpulse = 0;
- // limit part
- var newLimitImpulse;
- if (this.limitState != 2) {
- newLimitImpulse = (rvn - this.limitVelocity - this.limitImpulse * this.cfm) * this.invDenom;
- var oldLimitImpulse = this.limitImpulse;
- this.limitImpulse += newLimitImpulse;
- if (this.limitImpulse * this.limitState < 0) this.limitImpulse = 0;
- newLimitImpulse = this.limitImpulse - oldLimitImpulse;
- } else newLimitImpulse = 0;
- var totalImpulse = newLimitImpulse + newMotorImpulse;
- this.l1.x += totalImpulse * this.l1x;
- this.l1.y += totalImpulse * this.l1y;
- this.l1.z += totalImpulse * this.l1z;
- this.a1.x += totalImpulse * this.a1x;
- this.a1.y += totalImpulse * this.a1y;
- this.a1.z += totalImpulse * this.a1z;
- this.l2.x -= totalImpulse * this.l2x;
- this.l2.y -= totalImpulse * this.l2y;
- this.l2.z -= totalImpulse * this.l2z;
- this.a2.x -= totalImpulse * this.a2x;
- this.a2.y -= totalImpulse * this.a2y;
- this.a2.z -= totalImpulse * this.a2z;
- }
- }
- /**
- * A contact is a pair of shapes whose axis-aligned bounding boxes are overlapping.
- * @author saharan
- */
- OIMO.Contact = function () {
- // The first shape.
- this.shape1 = null;
- // The second shape.
- this.shape2 = null;
- // The first rigid body.
- this.body1 = null;
- // The second rigid body.
- this.body2 = null;
- // The previous contact in the world.
- this.prev = null;
- // The next contact in the world.
- this.next = null;
- // Internal
- this.persisting = false;
- // Whether both the rigid bodies are sleeping or not.
- this.sleeping = false;
- // The collision detector between two shapes.
- this.detector = null;
- // The contact constraint of the contact.
- this.constraint = null;
- // Whether the shapes are touching or not.
- this.touching = false;
- this.b1Link = new OIMO.ContactLink(this);
- this.b2Link = new OIMO.ContactLink(this);
- this.s1Link = new OIMO.ContactLink(this);
- this.s2Link = new OIMO.ContactLink(this);
- // The contact manifold of the contact.
- this.manifold = new OIMO.ContactManifold();
- this.buffer = [];// vector 4
- this.buffer.length = 4;
- this.buffer[0] = new OIMO.ImpulseDataBuffer();
- this.buffer[1] = new OIMO.ImpulseDataBuffer();
- this.buffer[2] = new OIMO.ImpulseDataBuffer();
- this.buffer[3] = new OIMO.ImpulseDataBuffer();
- this.points = this.manifold.points;
- this.constraint = new OIMO.ContactConstraint(this.manifold);
- }
- OIMO.Contact.prototype = {
- constructor: OIMO.Contact,
- mixRestitution: function (restitution1, restitution2) {
- return OIMO.sqrt(restitution1 * restitution2);
- },
- mixFriction: function (friction1, friction2) {
- return OIMO.sqrt(friction1 * friction2);
- },
- /**
- * Update the contact manifold.
- */
- updateManifold: function () {
- this.constraint.restitution = this.mixRestitution(this.shape1.restitution, this.shape2.restitution);
- this.constraint.friction = this.mixFriction(this.shape1.friction, this.shape2.friction);
- var numBuffers = this.manifold.numPoints;
- var i = numBuffers;
- while (i--) {
- //for(var i=0;i<numBuffers;i++){
- var b = this.buffer[i];
- var p = this.points[i];
- b.lp1X = p.localPoint1.x;
- b.lp1Y = p.localPoint1.y;
- b.lp1Z = p.localPoint1.z;
- b.lp2X = p.localPoint2.x;
- b.lp2Y = p.localPoint2.y;
- b.lp2Z = p.localPoint2.z;
- b.impulse = p.normalImpulse;
- }
- this.manifold.numPoints = 0;
- this.detector.detectCollision(this.shape1, this.shape2, this.manifold);
- var num = this.manifold.numPoints;
- if (num == 0) {
- this.touching = false;
- return;
- }
- this.touching = true;
- i = num;
- while (i--) {
- //for(i=0; i<num; i++){
- p = this.points[i];
- var lp1x = p.localPoint1.x;
- var lp1y = p.localPoint1.y;
- var lp1z = p.localPoint1.z;
- var lp2x = p.localPoint2.x;
- var lp2y = p.localPoint2.y;
- var lp2z = p.localPoint2.z;
- var index = -1;
- var minDistance = 0.0004;
- var j = numBuffers;
- while (j--) {
- //for(var j=0;j<numBuffers;j++){
- b = this.buffer[j];
- var dx = b.lp1X - lp1x;
- var dy = b.lp1Y - lp1y;
- var dz = b.lp1Z - lp1z;
- var distance1 = dx * dx + dy * dy + dz * dz;
- dx = b.lp2X - lp2x;
- dy = b.lp2Y - lp2y;
- dz = b.lp2Z - lp2z;
- var distance2 = dx * dx + dy * dy + dz * dz;
- if (distance1 < distance2) {
- if (distance1 < minDistance) {
- minDistance = distance1;
- index = j;
- }
- } else {
- if (distance2 < minDistance) {
- minDistance = distance2;
- index = j;
- }
- }
- }
- if (index != -1) {
- var tmp = this.buffer[index];
- this.buffer[index] = this.buffer[--numBuffers];
- this.buffer[numBuffers] = tmp;
- p.normalImpulse = tmp.impulse;
- p.warmStarted = true;
- } else {
- p.normalImpulse = 0;
- p.warmStarted = false;
- }
- }
- },
- /**
- * Attach the contact to the shapes.
- * @param shape1
- * @param shape2
- */
- attach: function (shape1, shape2) {
- this.shape1 = shape1;
- this.shape2 = shape2;
- this.body1 = shape1.parent;
- this.body2 = shape2.parent;
- this.manifold.body1 = this.body1;
- this.manifold.body2 = this.body2;
- this.constraint.body1 = this.body1;
- this.constraint.body2 = this.body2;
- this.constraint.attach();
- this.s1Link.shape = shape2;
- this.s1Link.body = this.body2;
- this.s2Link.shape = shape1;
- this.s2Link.body = this.body1;
- if (shape1.contactLink != null) (this.s1Link.next = shape1.contactLink).prev = this.s1Link;
- else this.s1Link.next = null;
- shape1.contactLink = this.s1Link;
- shape1.numContacts++;
- if (shape2.contactLink != null) (this.s2Link.next = shape2.contactLink).prev = this.s2Link;
- else this.s2Link.next = null;
- shape2.contactLink = this.s2Link;
- shape2.numContacts++;
- this.b1Link.shape = shape2;
- this.b1Link.body = this.body2;
- this.b2Link.shape = shape1;
- this.b2Link.body = this.body1;
- if (this.body1.contactLink != null) (this.b1Link.next = this.body1.contactLink).prev = this.b1Link;
- else this.b1Link.next = null;
- this.body1.contactLink = this.b1Link;
- this.body1.numContacts++;
- if (this.body2.contactLink != null) (this.b2Link.next = this.body2.contactLink).prev = this.b2Link;
- else this.b2Link.next = null;
- this.body2.contactLink = this.b2Link;
- this.body2.numContacts++;
- this.prev = null;
- this.next = null;
- this.persisting = true;
- this.sleeping = this.body1.sleeping && this.body2.sleeping;
- this.manifold.numPoints = 0;
- },
- /**
- * Detach the contact from the shapes.
- */
- detach: function () {
- var prev = this.s1Link.prev;
- var next = this.s1Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.shape1.contactLink == this.s1Link) this.shape1.contactLink = next;
- this.s1Link.prev = null;
- this.s1Link.next = null;
- this.s1Link.shape = null;
- this.s1Link.body = null;
- this.shape1.numContacts--;
- prev = this.s2Link.prev;
- next = this.s2Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.shape2.contactLink == this.s2Link) this.shape2.contactLink = next;
- this.s2Link.prev = null;
- this.s2Link.next = null;
- this.s2Link.shape = null;
- this.s2Link.body = null;
- this.shape2.numContacts--;
- prev = this.b1Link.prev;
- next = this.b1Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.body1.contactLink == this.b1Link) this.body1.contactLink = next;
- this.b1Link.prev = null;
- this.b1Link.next = null;
- this.b1Link.shape = null;
- this.b1Link.body = null;
- this.body1.numContacts--;
- prev = this.b2Link.prev;
- next = this.b2Link.next;
- if (prev !== null) prev.next = next;
- if (next !== null) next.prev = prev;
- if (this.body2.contactLink == this.b2Link) this.body2.contactLink = next;
- this.b2Link.prev = null;
- this.b2Link.next = null;
- this.b2Link.shape = null;
- this.b2Link.body = null;
- this.body2.numContacts--;
- this.manifold.body1 = null;
- this.manifold.body2 = null;
- this.constraint.body1 = null;
- this.constraint.body2 = null;
- this.constraint.detach();
- this.shape1 = null;
- this.shape2 = null;
- this.body1 = null;
- this.body2 = null;
- }
- }
- /**
- * ...
- * @author saharan
- */
- OIMO.ContactConstraint = function (manifold) {
- OIMO.Constraint.call(this);
- // The contact manifold of the constraint.
- this.manifold = manifold;
- // The coefficient of restitution of the constraint.
- this.restitution = NaN;
- // The coefficient of friction of the constraint.
- this.friction = NaN;
- this.p1 = null;
- this.p2 = null;
- this.lv1 = null;
- this.lv2 = null;
- this.av1 = null;
- this.av2 = null;
- this.i1 = null;
- this.i2 = null;
- this.ii1 = null;
- this.ii2 = null;
- this.m1 = NaN;
- this.m2 = NaN;
- this.num = 0;
- this.ps = manifold.points;
- this.cs = new OIMO.ContactPointDataBuffer();
- this.cs.next = new OIMO.ContactPointDataBuffer();
- this.cs.next.next = new OIMO.ContactPointDataBuffer();
- this.cs.next.next.next = new OIMO.ContactPointDataBuffer();
- }
- OIMO.ContactConstraint.prototype = Object.create(OIMO.Constraint.prototype);
- /**
- * Attach the constraint to the bodies.
- */
- OIMO.ContactConstraint.prototype.attach = function () {
- this.p1 = this.body1.position;
- this.p2 = this.body2.position;
- this.lv1 = this.body1.linearVelocity;
- this.av1 = this.body1.angularVelocity;
- this.lv2 = this.body2.linearVelocity;
- this.av2 = this.body2.angularVelocity;
- this.i1 = this.body1.inverseInertia;
- this.i2 = this.body2.inverseInertia;
- }
- /**
- * Detach the constraint from the bodies.
- */
- OIMO.ContactConstraint.prototype.detach = function () {
- this.p1 = null;
- this.p2 = null;
- this.lv1 = null;
- this.lv2 = null;
- this.av1 = null;
- this.av2 = null;
- this.i1 = null;
- this.i2 = null;
- }
- OIMO.ContactConstraint.prototype.preSolve = function (timeStep, invTimeStep) {
- this.m1 = this.body1.inverseMass;
- this.m2 = this.body2.inverseMass;
- this.ii1 = this.i1.clone();
- this.ii2 = this.i2.clone();
- var ii1 = this.ii1.elements;
- var ii2 = this.ii2.elements;
- var p1x = this.p1.x;
- var p1y = this.p1.y;
- var p1z = this.p1.z;
- var p2x = this.p2.x;
- var p2y = this.p2.y;
- var p2z = this.p2.z;
- var m1m2 = this.m1 + this.m2;
- this.num = this.manifold.numPoints;
- var c = this.cs;
- for (var i = 0; i < this.num; i++) {
- var p = this.ps[i];
- var tmp1X;
- var tmp1Y;
- var tmp1Z;
- var tmp2X;
- var tmp2Y;
- var tmp2Z;
- tmp1X = p.position.x;
- tmp1Y = p.position.y;
- tmp1Z = p.position.z;
- var rp1X = tmp1X - p1x;
- var rp1Y = tmp1Y - p1y;
- var rp1Z = tmp1Z - p1z;
- var rp2X = tmp1X - p2x;
- var rp2Y = tmp1Y - p2y;
- var rp2Z = tmp1Z - p2z;
- c.rp1X = rp1X;
- c.rp1Y = rp1Y;
- c.rp1Z = rp1Z;
- c.rp2X = rp2X;
- c.rp2Y = rp2Y;
- c.rp2Z = rp2Z;
- c.norImp = p.normalImpulse;
- c.tanImp = p.tangentImpulse;
- c.binImp = p.binormalImpulse;
- var norX = p.normal.x;
- var norY = p.normal.y;
- var norZ = p.normal.z;
- var rvX = (this.lv2.x + this.av2.y * rp2Z - this.av2.z * rp2Y) - (this.lv1.x + this.av1.y * rp1Z - this.av1.z * rp1Y);
- var rvY = (this.lv2.y + this.av2.z * rp2X - this.av2.x * rp2Z) - (this.lv1.y + this.av1.z * rp1X - this.av1.x * rp1Z);
- var rvZ = (this.lv2.z + this.av2.x * rp2Y - this.av2.y * rp2X) - (this.lv1.z + this.av1.x * rp1Y - this.av1.y * rp1X);
- var rvn = norX * rvX + norY * rvY + norZ * rvZ;
- var tanX = rvX - rvn * norX;
- var tanY = rvY - rvn * norY;
- var tanZ = rvZ - rvn * norZ;
- var len = tanX * tanX + tanY * tanY + tanZ * tanZ;
- if (len > 0.04) {
- len = 1 / OIMO.sqrt(len);
- } else {
- tanX = norY * norX - norZ * norZ;
- tanY = -norZ * norY - norX * norX;
- tanZ = norX * norZ + norY * norY;
- len = 1 / OIMO.sqrt(tanX * tanX + tanY * tanY + tanZ * tanZ);
- }
- tanX *= len;
- tanY *= len;
- tanZ *= len;
- var binX = norY * tanZ - norZ * tanY;
- var binY = norZ * tanX - norX * tanZ;
- var binZ = norX * tanY - norY * tanX;
- c.norX = norX;
- c.norY = norY;
- c.norZ = norZ;
- c.tanX = tanX;
- c.tanY = tanY;
- c.tanZ = tanZ;
- c.binX = binX;
- c.binY = binY;
- c.binZ = binZ;
- c.norU1X = norX * this.m1;
- c.norU1Y = norY * this.m1;
- c.norU1Z = norZ * this.m1;
- c.norU2X = norX * this.m2;
- c.norU2Y = norY * this.m2;
- c.norU2Z = norZ * this.m2;
- c.tanU1X = tanX * this.m1;
- c.tanU1Y = tanY * this.m1;
- c.tanU1Z = tanZ * this.m1;
- c.tanU2X = tanX * this.m2;
- c.tanU2Y = tanY * this.m2;
- c.tanU2Z = tanZ * this.m2;
- c.binU1X = binX * this.m1;
- c.binU1Y = binY * this.m1;
- c.binU1Z = binZ * this.m1;
- c.binU2X = binX * this.m2;
- c.binU2Y = binY * this.m2;
- c.binU2Z = binZ * this.m2;
- var norT1X = rp1Y * norZ - rp1Z * norY;
- var norT1Y = rp1Z * norX - rp1X * norZ;
- var norT1Z = rp1X * norY - rp1Y * norX;
- var norT2X = rp2Y * norZ - rp2Z * norY;
- var norT2Y = rp2Z * norX - rp2X * norZ;
- var norT2Z = rp2X * norY - rp2Y * norX;
- var tanT1X = rp1Y * tanZ - rp1Z * tanY;
- var tanT1Y = rp1Z * tanX - rp1X * tanZ;
- var tanT1Z = rp1X * tanY - rp1Y * tanX;
- var tanT2X = rp2Y * tanZ - rp2Z * tanY;
- var tanT2Y = rp2Z * tanX - rp2X * tanZ;
- var tanT2Z = rp2X * tanY - rp2Y * tanX;
- var binT1X = rp1Y * binZ - rp1Z * binY;
- var binT1Y = rp1Z * binX - rp1X * binZ;
- var binT1Z = rp1X * binY - rp1Y * binX;
- var binT2X = rp2Y * binZ - rp2Z * binY;
- var binT2Y = rp2Z * binX - rp2X * binZ;
- var binT2Z = rp2X * binY - rp2Y * binX;
- var norTU1X = norT1X * ii1[0] + norT1Y * ii1[1] + norT1Z * ii1[2];
- var norTU1Y = norT1X * ii1[3] + norT1Y * ii1[4] + norT1Z * ii1[5];
- var norTU1Z = norT1X * ii1[6] + norT1Y * ii1[7] + norT1Z * ii1[8];
- var norTU2X = norT2X * ii2[0] + norT2Y * ii2[1] + norT2Z * ii2[2];
- var norTU2Y = norT2X * ii2[3] + norT2Y * ii2[4] + norT2Z * ii2[5];
- var norTU2Z = norT2X * ii2[6] + norT2Y * ii2[7] + norT2Z * ii2[8];
- var tanTU1X = tanT1X * ii1[0] + tanT1Y * ii1[1] + tanT1Z * ii1[2];
- var tanTU1Y = tanT1X * ii1[3] + tanT1Y * ii1[4] + tanT1Z * ii1[5];
- var tanTU1Z = tanT1X * ii1[6] + tanT1Y * ii1[7] + tanT1Z * ii1[8];
- var tanTU2X = tanT2X * ii2[0] + tanT2Y * ii2[1] + tanT2Z * ii2[2];
- var tanTU2Y = tanT2X * ii2[3] + tanT2Y * ii2[4] + tanT2Z * ii2[5];
- var tanTU2Z = tanT2X * ii2[6] + tanT2Y * ii2[7] + tanT2Z * ii2[8];
- var binTU1X = binT1X * ii1[0] + binT1Y * ii1[1] + binT1Z * ii1[2];
- var binTU1Y = binT1X * ii1[3] + binT1Y * ii1[4] + binT1Z * ii1[5];
- var binTU1Z = binT1X * ii1[6] + binT1Y * ii1[7] + binT1Z * ii1[8];
- var binTU2X = binT2X * ii2[0] + binT2Y * ii2[1] + binT2Z * ii2[2];
- var binTU2Y = binT2X * ii2[3] + binT2Y * ii2[4] + binT2Z * ii2[5];
- var binTU2Z = binT2X * ii2[6] + binT2Y * ii2[7] + binT2Z * ii2[8];
- c.norT1X = norT1X;
- c.norT1Y = norT1Y;
- c.norT1Z = norT1Z;
- c.tanT1X = tanT1X;
- c.tanT1Y = tanT1Y;
- c.tanT1Z = tanT1Z;
- c.binT1X = binT1X;
- c.binT1Y = binT1Y;
- c.binT1Z = binT1Z;
- c.norT2X = norT2X;
- c.norT2Y = norT2Y;
- c.norT2Z = norT2Z;
- c.tanT2X = tanT2X;
- c.tanT2Y = tanT2Y;
- c.tanT2Z = tanT2Z;
- c.binT2X = binT2X;
- c.binT2Y = binT2Y;
- c.binT2Z = binT2Z;
- c.norTU1X = norTU1X;
- c.norTU1Y = norTU1Y;
- c.norTU1Z = norTU1Z;
- c.tanTU1X = tanTU1X;
- c.tanTU1Y = tanTU1Y;
- c.tanTU1Z = tanTU1Z;
- c.binTU1X = binTU1X;
- c.binTU1Y = binTU1Y;
- c.binTU1Z = binTU1Z;
- c.norTU2X = norTU2X;
- c.norTU2Y = norTU2Y;
- c.norTU2Z = norTU2Z;
- c.tanTU2X = tanTU2X;
- c.tanTU2Y = tanTU2Y;
- c.tanTU2Z = tanTU2Z;
- c.binTU2X = binTU2X;
- c.binTU2Y = binTU2Y;
- c.binTU2Z = binTU2Z;
- tmp1X = norT1X * ii1[0] + norT1Y * ii1[1] + norT1Z * ii1[2];
- tmp1Y = norT1X * ii1[3] + norT1Y * ii1[4] + norT1Z * ii1[5];
- tmp1Z = norT1X * ii1[6] + norT1Y * ii1[7] + norT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = norT2X * ii2[0] + norT2Y * ii2[1] + norT2Z * ii2[2];
- tmp1Y = norT2X * ii2[3] + norT2Y * ii2[4] + norT2Z * ii2[5];
- tmp1Z = norT2X * ii2[6] + norT2Y * ii2[7] + norT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var norDen = 1 / (m1m2 + norX * tmp2X + norY * tmp2Y + norZ * tmp2Z);
- tmp1X = tanT1X * ii1[0] + tanT1Y * ii1[1] + tanT1Z * ii1[2];
- tmp1Y = tanT1X * ii1[3] + tanT1Y * ii1[4] + tanT1Z * ii1[5];
- tmp1Z = tanT1X * ii1[6] + tanT1Y * ii1[7] + tanT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = tanT2X * ii2[0] + tanT2Y * ii2[1] + tanT2Z * ii2[2];
- tmp1Y = tanT2X * ii2[3] + tanT2Y * ii2[4] + tanT2Z * ii2[5];
- tmp1Z = tanT2X * ii2[6] + tanT2Y * ii2[7] + tanT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var tanDen = 1 / (m1m2 + tanX * tmp2X + tanY * tmp2Y + tanZ * tmp2Z);
- tmp1X = binT1X * ii1[0] + binT1Y * ii1[1] + binT1Z * ii1[2];
- tmp1Y = binT1X * ii1[3] + binT1Y * ii1[4] + binT1Z * ii1[5];
- tmp1Z = binT1X * ii1[6] + binT1Y * ii1[7] + binT1Z * ii1[8];
- tmp2X = tmp1Y * rp1Z - tmp1Z * rp1Y;
- tmp2Y = tmp1Z * rp1X - tmp1X * rp1Z;
- tmp2Z = tmp1X * rp1Y - tmp1Y * rp1X;
- tmp1X = binT2X * ii2[0] + binT2Y * ii2[1] + binT2Z * ii2[2];
- tmp1Y = binT2X * ii2[3] + binT2Y * ii2[4] + binT2Z * ii2[5];
- tmp1Z = binT2X * ii2[6] + binT2Y * ii2[7] + binT2Z * ii2[8];
- tmp2X += tmp1Y * rp2Z - tmp1Z * rp2Y;
- tmp2Y += tmp1Z * rp2X - tmp1X * rp2Z;
- tmp2Z += tmp1X * rp2Y - tmp1Y * rp2X;
- var binDen = 1 / (m1m2 + binX * tmp2X + binY * tmp2Y + binZ * tmp2Z);
- c.norDen = norDen;
- c.tanDen = tanDen;
- c.binDen = binDen;
- if (p.warmStarted) {
- var norImp = p.normalImpulse;
- this.lv1.x += c.norU1X * norImp;
- this.lv1.y += c.norU1Y * norImp;
- this.lv1.z += c.norU1Z * norImp;
- this.av1.x += norTU1X * norImp;
- this.av1.y += norTU1Y * norImp;
- this.av1.z += norTU1Z * norImp;
- this.lv2.x -= c.norU2X * norImp;
- this.lv2.y -= c.norU2Y * norImp;
- this.lv2.z -= c.norU2Z * norImp;
- this.av2.x -= norTU2X * norImp;
- this.av2.y -= norTU2Y * norImp;
- this.av2.z -= norTU2Z * norImp;
- c.norImp = norImp;
- c.tanImp = 0;
- c.binImp = 0;
- rvn = 0; // disable bouncing
- } else {
- c.norImp = 0;
- c.tanImp = 0;
- c.binImp = 0;
- }
- if (rvn > -1) {
- rvn = 0; // disable bouncing
- }
- var norTar = this.restitution * -rvn;
- var sepV = -(p.penetration + 0.005) * invTimeStep * 0.05; // allow 0.5cm error
- if (norTar < sepV) norTar = sepV;
- c.norTar = norTar;
- c.last = i == this.num - 1;
- c = c.next;
- }
- }
- OIMO.ContactConstraint.prototype.solve = function () {
- var lv1x = this.lv1.x;
- var lv1y = this.lv1.y;
- var lv1z = this.lv1.z;
- var lv2x = this.lv2.x;
- var lv2y = this.lv2.y;
- var lv2z = this.lv2.z;
- var av1x = this.av1.x;
- var av1y = this.av1.y;
- var av1z = this.av1.z;
- var av2x = this.av2.x;
- var av2y = this.av2.y;
- var av2z = this.av2.z;
- var c = this.cs;
- while (true) {
- var oldImp1;
- var newImp1;
- var oldImp2;
- var newImp2;
- var rvn;
- var norImp = c.norImp;
- var tanImp = c.tanImp;
- var binImp = c.binImp;
- var max = -norImp * this.friction;
- var rvX = lv2x - lv1x;
- var rvY = lv2y - lv1y;
- var rvZ = lv2z - lv1z;
- rvn =
- rvX * c.tanX + rvY * c.tanY + rvZ * c.tanZ +
- av2x * c.tanT2X + av2y * c.tanT2Y + av2z * c.tanT2Z -
- av1x * c.tanT1X - av1y * c.tanT1Y - av1z * c.tanT1Z
- ;
- oldImp1 = tanImp;
- newImp1 = rvn * c.tanDen;
- tanImp += newImp1;
- rvn =
- rvX * c.binX + rvY * c.binY + rvZ * c.binZ +
- av2x * c.binT2X + av2y * c.binT2Y + av2z * c.binT2Z -
- av1x * c.binT1X - av1y * c.binT1Y - av1z * c.binT1Z
- ;
- oldImp2 = binImp;
- newImp2 = rvn * c.binDen;
- binImp += newImp2;
- // cone friction clamp
- var len = tanImp * tanImp + binImp * binImp;
- if (len > max * max) {
- len = max / OIMO.sqrt(len);
- tanImp *= len;
- binImp *= len;
- }
- newImp1 = tanImp - oldImp1;
- newImp2 = binImp - oldImp2;
- lv1x += c.tanU1X * newImp1 + c.binU1X * newImp2;
- lv1y += c.tanU1Y * newImp1 + c.binU1Y * newImp2;
- lv1z += c.tanU1Z * newImp1 + c.binU1Z * newImp2;
- av1x += c.tanTU1X * newImp1 + c.binTU1X * newImp2;
- av1y += c.tanTU1Y * newImp1 + c.binTU1Y * newImp2;
- av1z += c.tanTU1Z * newImp1 + c.binTU1Z * newImp2;
- lv2x -= c.tanU2X * newImp1 + c.binU2X * newImp2;
- lv2y -= c.tanU2Y * newImp1 + c.binU2Y * newImp2;
- lv2z -= c.tanU2Z * newImp1 + c.binU2Z * newImp2;
- av2x -= c.tanTU2X * newImp1 + c.binTU2X * newImp2;
- av2y -= c.tanTU2Y * newImp1 + c.binTU2Y * newImp2;
- av2z -= c.tanTU2Z * newImp1 + c.binTU2Z * newImp2;
- // restitution part
- rvn =
- (lv2x - lv1x) * c.norX + (lv2y - lv1y) * c.norY + (lv2z - lv1z) * c.norZ +
- av2x * c.norT2X + av2y * c.norT2Y + av2z * c.norT2Z -
- av1x * c.norT1X - av1y * c.norT1Y - av1z * c.norT1Z;
- oldImp1 = norImp;
- newImp1 = (rvn - c.norTar) * c.norDen;
- norImp += newImp1;
- if (norImp > 0) norImp = 0;
- newImp1 = norImp - oldImp1;
- lv1x += c.norU1X * newImp1;
- lv1y += c.norU1Y * newImp1;
- lv1z += c.norU1Z * newImp1;
- av1x += c.norTU1X * newImp1;
- av1y += c.norTU1Y * newImp1;
- av1z += c.norTU1Z * newImp1;
- lv2x -= c.norU2X * newImp1;
- lv2y -= c.norU2Y * newImp1;
- lv2z -= c.norU2Z * newImp1;
- av2x -= c.norTU2X * newImp1;
- av2y -= c.norTU2Y * newImp1;
- av2z -= c.norTU2Z * newImp1;
- c.norImp = norImp;
- c.tanImp = tanImp;
- c.binImp = binImp;
- if (c.last) break;
- c = c.next;
- }
- this.lv1.x = lv1x;
- this.lv1.y = lv1y;
- this.lv1.z = lv1z;
- this.lv2.x = lv2x;
- this.lv2.y = lv2y;
- this.lv2.z = lv2z;
- this.av1.x = av1x;
- this.av1.y = av1y;
- this.av1.z = av1z;
- this.av2.x = av2x;
- this.av2.y = av2y;
- this.av2.z = av2z;
- }
- OIMO.ContactConstraint.prototype.postSolve = function () {
- var c = this.cs;
- var i = this.num;
- while (i--) {
- //for(var i=0;i<this.num;i++){
- var p = this.ps[i];
- p.normal.x = c.norX;
- p.normal.y = c.norY;
- p.normal.z = c.norZ;
- p.tangent.x = c.tanX;
- p.tangent.y = c.tanY;
- p.tangent.z = c.tanZ;
- p.binormal.x = c.binX;
- p.binormal.y = c.binY;
- p.binormal.z = c.binZ;
- p.normalImpulse = c.norImp;
- p.tangentImpulse = c.tanImp;
- p.binormalImpulse = c.binImp;
- p.normalDenominator = c.norDen;
- p.tangentDenominator = c.tanDen;
- p.binormalDenominator = c.binDen;
- c = c.next;
- }
- }
- /**
- * A link list of contacts.
- * @author saharan
- */
- OIMO.ContactLink = function (contact) {
- // The previous contact link.
- this.prev = null;
- // The next contact link.
- this.next = null;
- // The shape of the contact.
- this.shape = null;
- // The other rigid body.
- this.body = null;
- // The contact of the link.
- this.contact = contact;
- }
- /**
- * A contact manifold between two shapes.
- * @author saharan
- */
- OIMO.ContactManifold = function () {
- // The first rigid body.
- this.body1 = null;
- // The second rigid body.
- this.body2 = null;
- // The number of manifold points.
- this.numPoints = 0;
- // The manifold points.
- this.points = [];
- this.points.length = 4;
- this.points[0] = new OIMO.ManifoldPoint();
- this.points[1] = new OIMO.ManifoldPoint();
- this.points[2] = new OIMO.ManifoldPoint();
- this.points[3] = new OIMO.ManifoldPoint();
- }
- OIMO.ContactManifold.prototype = {
- constructor: OIMO.ContactManifold,
- /**
- * Reset the manifold.
- * @param shape1
- * @param shape2
- */
- reset: function (shape1, shape2) {
- this.body1 = shape1.parent;
- this.body2 = shape2.parent;
- this.numPoints = 0;
- },
- /**
- * Add a point into this manifold.
- * @param x
- * @param y
- * @param z
- * @param normalX
- * @param normalY
- * @param normalZ
- * @param penetration
- * @param flip
- */
- addPoint: function (x, y, z, normalX, normalY, normalZ, penetration, flip) {
- var p = this.points[this.numPoints++];
- p.position.x = x;
- p.position.y = y;
- p.position.z = z;
- var r = this.body1.rotation;
- var rx = x - this.body1.position.x;
- var ry = y - this.body1.position.y;
- var rz = z - this.body1.position.z;
- var tr = r.elements;
- p.localPoint1.x = rx * tr[0] + ry * tr[3] + rz * tr[6];
- p.localPoint1.y = rx * tr[1] + ry * tr[4] + rz * tr[7];
- p.localPoint1.z = rx * tr[2] + ry * tr[5] + rz * tr[8];
- r = this.body2.rotation;
- rx = x - this.body2.position.x;
- ry = y - this.body2.position.y;
- rz = z - this.body2.position.z;
- p.localPoint2.x = rx * tr[0] + ry * tr[3] + rz * tr[6];
- p.localPoint2.y = rx * tr[1] + ry * tr[4] + rz * tr[7];
- p.localPoint2.z = rx * tr[2] + ry * tr[5] + rz * tr[8];
- p.normalImpulse = 0;
- if (flip) {
- p.normal.x = -normalX;
- p.normal.y = -normalY;
- p.normal.z = -normalZ;
- } else {
- p.normal.x = normalX;
- p.normal.y = normalY;
- p.normal.z = normalZ;
- }
- p.penetration = penetration;
- p.warmStarted = false;
- }
- }
- OIMO.ContactPointDataBuffer = function () {
- this.norX = NaN;
- this.norY = NaN;
- this.norZ = NaN;
- this.tanX = NaN;
- this.tanY = NaN;
- this.tanZ = NaN;
- this.binX = NaN;
- this.binY = NaN;
- this.binZ = NaN;
- this.rp1X = NaN;
- this.rp1Y = NaN;
- this.rp1Z = NaN;
- this.rp2X = NaN;
- this.rp2Y = NaN;
- this.rp2Z = NaN;
- this.norU1X = NaN;
- this.norU1Y = NaN;
- this.norU1Z = NaN;
- this.norU2X = NaN;
- this.norU2Y = NaN;
- this.norU2Z = NaN;
- this.tanU1X = NaN;
- this.tanU1Y = NaN;
- this.tanU1Z = NaN;
- this.tanU2X = NaN;
- this.tanU2Y = NaN;
- this.tanU2Z = NaN;
- this.binU1X = NaN;
- this.binU1Y = NaN;
- this.binU1Z = NaN;
- this.binU2X = NaN;
- this.binU2Y = NaN;
- this.binU2Z = NaN;
- this.norT1X = NaN;
- this.norT1Y = NaN;
- this.norT1Z = NaN;
- this.norT2X = NaN;
- this.norT2Y = NaN;
- this.norT2Z = NaN;
- this.tanT1X = NaN;
- this.tanT1Y = NaN;
- this.tanT1Z = NaN;
- this.tanT2X = NaN;
- this.tanT2Y = NaN;
- this.tanT2Z = NaN;
- this.binT1X = NaN;
- this.binT1Y = NaN;
- this.binT1Z = NaN;
- this.binT2X = NaN;
- this.binT2Y = NaN;
- this.binT2Z = NaN;
- this.norTU1X = NaN;
- this.norTU1Y = NaN;
- this.norTU1Z = NaN;
- this.norTU2X = NaN;
- this.norTU2Y = NaN;
- this.norTU2Z = NaN;
- this.tanTU1X = NaN;
- this.tanTU1Y = NaN;
- this.tanTU1Z = NaN;
- this.tanTU2X = NaN;
- this.tanTU2Y = NaN;
- this.tanTU2Z = NaN;
- this.binTU1X = NaN;
- this.binTU1Y = NaN;
- this.binTU1Z = NaN;
- this.binTU2X = NaN;
- this.binTU2Y = NaN;
- this.binTU2Z = NaN;
- this.norImp = NaN;
- this.tanImp = NaN;
- this.binImp = NaN;
- this.norDen = NaN;
- this.tanDen = NaN;
- this.binDen = NaN;
- this.norTar = NaN;
- this.next = null;
- this.last = false;
- }
- OIMO.ImpulseDataBuffer = function () {
- this.lp1X = NaN;
- this.lp1Y = NaN;
- this.lp1Z = NaN;
- this.lp2X = NaN;
- this.lp2Y = NaN;
- this.lp2Z = NaN;
- this.impulse = NaN;
- }
- /**
- * The class holds details of the contact point.
- * @author saharan
- */
- OIMO.ManifoldPoint = function () {
- // Whether this manifold point is persisting or not.
- this.warmStarted = false;
- // The position of this manifold point.
- this.position = new OIMO.Vec3();
- // The position in the first shape's coordinate.
- this.localPoint1 = new OIMO.Vec3();
- // The position in the second shape's coordinate.
- this.localPoint2 = new OIMO.Vec3();
- // The normal vector of this manifold point.
- this.normal = new OIMO.Vec3();
- // The tangent vector of this manifold point.
- this.tangent = new OIMO.Vec3();
- // The binormal vector of this manifold point.
- this.binormal = new OIMO.Vec3();
- // The impulse in normal direction.
- this.normalImpulse = 0;
- // The impulse in tangent direction.
- this.tangentImpulse = 0;
- // The impulse in binormal direction.
- this.binormalImpulse = 0;
- // The denominator in normal direction.
- this.normalDenominator = 0;
- // The denominator in tangent direction.
- this.tangentDenominator = 0;
- // The denominator in binormal direction.
- this.binormalDenominator = 0;
- // The depth of penetration.
- this.penetration = 0;
- }
- /**
- * This class holds mass information of a shape.
- * @author saharan
- */
- OIMO.MassInfo = function () {
- // Mass of the shape.
- this.mass = 0;
- // The moment inertia of the shape.
- this.inertia = new OIMO.Mat33();
- };
- /**
- * A shape is used to detect collisions of rigid bodies.
- * @author saharan
- * @author lo-th
- */
- OIMO.Shape = function (config) {
- this.type = OIMO.SHAPE_NULL;
- // The global identification of the shape should be unique to the shape.
- this.id = OIMO.nextID++;
- // The previous shape in parent rigid body.
- this.prev = null;
- // The next shape in parent rigid body.
- this.next = null;
- // The proxy of the shape used for broad-phase collision detection.
- this.proxy = null;
- // The parent rigid body of the shape.
- this.parent = null;
- // The linked list of the contacts with the shape.
- this.contactLink = null;
- // The number of the contacts with the shape.
- this.numContacts = 0;
- // The center of gravity of the shape in world coordinate system.
- this.position = new OIMO.Vec3();
- // The rotation matrix of the shape in world coordinate system
- this.rotation = new OIMO.Mat33();
- // The position of the shape in parent's coordinate system.
- this.relativePosition = new OIMO.Vec3().copy(config.relativePosition);
- // The rotation matrix of the shape in parent's coordinate system.
- this.relativeRotation = new OIMO.Mat33().copy(config.relativeRotation);
- // The axis-aligned bounding box of the shape.
- this.aabb = new OIMO.AABB();
- // The density of the shape.
- this.density = config.density;
- // The coefficient of friction of the shape.
- this.friction = config.friction;
- // The coefficient of restitution of the shape.
- this.restitution = config.restitution;
- // The bits of the collision groups to which the shape belongs.
- this.belongsTo = config.belongsTo;
- // The bits of the collision groups with which the shape collides.
- this.collidesWith = config.collidesWith;
- };
- OIMO.Shape.prototype = {
- constructor: OIMO.Shape,
- // Calculate the mass information of the shape.
- calculateMassInfo: function (out) {
- OIMO.Error("Shape", "Inheritance error.");
- },
- // Update the proxy of the shape.
- updateProxy: function () {
- OIMO.Error("Shape", "Inheritance error.");
- }
- };
- /**
- * A shape configuration holds common configuration data for constructing a shape.
- * Shape configurations can be reused safely.
- * @author saharan
- */
- OIMO.ShapeConfig = function () {
- // The position of the shape in parent's coordinate system.
- this.relativePosition = new OIMO.Vec3();
- // The rotation matrix of the shape in parent's coordinate system.
- this.relativeRotation = new OIMO.Mat33();
- // The coefficient of friction of the shape.
- this.friction = 0.4;
- // The coefficient of restitution of the shape.
- this.restitution = 0.2;
- // The density of the shape.
- this.density = 1;
- // The bits of the collision groups to which the shape belongs.
- this.belongsTo = 1;
- // The bits of the collision groups with which the shape collides.
- this.collidesWith = 0xffffffff;
- };
- /**
- * A box shape.
- * @author saharan
- * @author lo-th
- */
- OIMO.BoxShape = function (config, Width, Height, Depth) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_BOX;
- // The width of the box.
- this.width = Width;
- // The height of the box.
- this.height = Height;
- // The depth of the box.
- this.depth = Depth;
- // The half-width of the box.
- this.halfWidth = Width * 0.5;
- // The half-height of the box.
- this.halfHeight = Height * 0.5;
- // The half-depth of the box.
- this.halfDepth = Depth * 0.5;
- this.dimentions = new OIMO_ARRAY_TYPE(18);
- this.elements = new OIMO_ARRAY_TYPE(24);
- };
- OIMO.BoxShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.BoxShape.prototype.constructor = OIMO.BoxShape;
- OIMO.BoxShape.prototype.calculateMassInfo = function (out) {
- var mass = this.width * this.height * this.depth * this.density;
- var divid = 1 / 12;
- out.mass = mass;
- out.inertia.set(
- mass * (this.height * this.height + this.depth * this.depth) * divid, 0, 0,
- 0, mass * (this.width * this.width + this.depth * this.depth) * divid, 0,
- 0, 0, mass * (this.width * this.width + this.height * this.height) * divid
- );
- };
- OIMO.BoxShape.prototype.updateProxy = function () {
- var te = this.rotation.elements;
- var di = this.dimentions;
- // Width
- di[0] = te[0];
- di[1] = te[3];
- di[2] = te[6];
- // Height
- di[3] = te[1];
- di[4] = te[4];
- di[5] = te[7];
- // Depth
- di[6] = te[2];
- di[7] = te[5];
- di[8] = te[8];
- // halp Width
- di[9] = te[0] * this.halfWidth;
- di[10] = te[3] * this.halfWidth;
- di[11] = te[6] * this.halfWidth;
- // halp Height
- di[12] = te[1] * this.halfHeight;
- di[13] = te[4] * this.halfHeight;
- di[14] = te[7] * this.halfHeight;
- // halp Depth
- di[15] = te[2] * this.halfDepth;
- di[16] = te[5] * this.halfDepth;
- di[17] = te[8] * this.halfDepth;
- var wx = di[9];
- var wy = di[10];
- var wz = di[11];
- var hx = di[12];
- var hy = di[13];
- var hz = di[14];
- var dx = di[15];
- var dy = di[16];
- var dz = di[17];
- var x = this.position.x;
- var y = this.position.y;
- var z = this.position.z;
- var v = this.elements;
- //v1
- v[0] = x + wx + hx + dx;
- v[1] = y + wy + hy + dy;
- v[2] = z + wz + hz + dz;
- //v2
- v[3] = x + wx + hx - dx;
- v[4] = y + wy + hy - dy;
- v[5] = z + wz + hz - dz;
- //v3
- v[6] = x + wx - hx + dx;
- v[7] = y + wy - hy + dy;
- v[8] = z + wz - hz + dz;
- //v4
- v[9] = x + wx - hx - dx;
- v[10] = y + wy - hy - dy;
- v[11] = z + wz - hz - dz;
- //v5
- v[12] = x - wx + hx + dx;
- v[13] = y - wy + hy + dy;
- v[14] = z - wz + hz + dz;
- //v6
- v[15] = x - wx + hx - dx;
- v[16] = y - wy + hy - dy;
- v[17] = z - wz + hz - dz;
- //v7
- v[18] = x - wx - hx + dx;
- v[19] = y - wy - hy + dy;
- v[20] = z - wz - hz + dz;
- //v8
- v[21] = x - wx - hx - dx;
- v[22] = y - wy - hy - dy;
- v[23] = z - wz - hz - dz;
- var w = di[9] < 0 ? -di[9] : di[9];
- var h = di[10] < 0 ? -di[10] : di[10];
- var d = di[11] < 0 ? -di[11] : di[11];
- w = di[12] < 0 ? w - di[12] : w + di[12];
- h = di[13] < 0 ? h - di[13] : h + di[13];
- d = di[14] < 0 ? d - di[14] : d + di[14];
- w = di[15] < 0 ? w - di[15] : w + di[15];
- h = di[16] < 0 ? h - di[16] : h + di[16];
- d = di[17] < 0 ? d - di[17] : d + di[17];
- var p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - w - p, this.position.x + w + p,
- this.position.y - h - p, this.position.y + h + p,
- this.position.z - d - p, this.position.z + d + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A sphere shape.
- * @author saharan
- * @author lo-th
- */
- OIMO.SphereShape = function (config, radius) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_SPHERE;
- // The radius of the shape.
- this.radius = radius;
- };
- OIMO.SphereShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.SphereShape.prototype.constructor = OIMO.SphereShape;
- OIMO.SphereShape.prototype.calculateMassInfo = function (out) {
- var mass = 1.333 * OIMO.PI * this.radius * this.radius * this.radius * this.density;
- out.mass = mass;
- var inertia = mass * this.radius * this.radius * 0.4;
- out.inertia.set(inertia, 0, 0, 0, inertia, 0, 0, 0, inertia);
- };
- OIMO.SphereShape.prototype.updateProxy = function () {
- var p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - this.radius - p, this.position.x + this.radius + p,
- this.position.y - this.radius - p, this.position.y + this.radius + p,
- this.position.z - this.radius - p, this.position.z + this.radius + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A cylinder shap.
- * @author saharan
- * @author lo-th
- */
- OIMO.CylinderShape = function (config, radius, height) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_CYLINDER;
- this.radius = radius;
- this.height = height;
- this.halfHeight = height * 0.5;
- this.normalDirection = new OIMO.Vec3();
- this.halfDirection = new OIMO.Vec3();
- };
- OIMO.CylinderShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.CylinderShape.prototype.constructor = OIMO.CylinderShape;
- OIMO.CylinderShape.prototype.calculateMassInfo = function (out) {
- var rsq = this.radius * this.radius;
- var mass = OIMO.PI * rsq * this.height * this.density;
- var inertiaXZ = ((0.25 * rsq) + (0.0833 * this.height * this.height)) * mass;
- var inertiaY = 0.5 * rsq;
- out.mass = mass;
- out.inertia.set(inertiaXZ, 0, 0, 0, inertiaY, 0, 0, 0, inertiaXZ);
- };
- OIMO.CylinderShape.prototype.updateProxy = function () {
- var te = this.rotation.elements;
- var len, wx, hy, dz, xx, yy, zz, w, h, d, p;
- xx = te[1] * te[1];
- yy = te[4] * te[4];
- zz = te[7] * te[7];
- this.normalDirection.set(te[1], te[4], te[7]);
- this.halfDirection.scale(this.normalDirection, this.halfHeight);
- wx = 1 - xx;
- len = OIMO.sqrt(wx * wx + xx * yy + xx * zz);
- if (len > 0) len = this.radius / len;
- wx *= len;
- hy = 1 - yy;
- len = OIMO.sqrt(yy * xx + hy * hy + yy * zz);
- if (len > 0) len = this.radius / len;
- hy *= len;
- dz = 1 - zz;
- len = OIMO.sqrt(zz * xx + zz * yy + dz * dz);
- if (len > 0) len = this.radius / len;
- dz *= len;
- w = this.halfDirection.x < 0 ? -this.halfDirection.x : this.halfDirection.x;
- h = this.halfDirection.y < 0 ? -this.halfDirection.y : this.halfDirection.y;
- d = this.halfDirection.z < 0 ? -this.halfDirection.z : this.halfDirection.z;
- w = wx < 0 ? w - wx : w + wx;
- h = hy < 0 ? h - hy : h + hy;
- d = dz < 0 ? d - dz : d + dz;
- p = OIMO.AABB_PROX;
- this.aabb.set(
- this.position.x - w - p, this.position.x + w + p,
- this.position.y - h - p, this.position.y + h + p,
- this.position.z - d - p, this.position.z + d + p
- );
- if (this.proxy != null) this.proxy.update();
- };
- /**
- * A tetra shape.
- * @author xprogram
- */
- OIMO.TetraShape = function (config, p1, p2, p3, p4) {
- OIMO.Shape.call(this, config);
- this.type = OIMO.SHAPE_TETRA;
- // Vertices and faces of tetra
- this.verts = [p1, p2, p3, p4];
- this.faces = [
- mtri(0, 1, 2),
- mtri(1, 2, 3),
- mtri(2, 3, 4),
- mtri(4, 0, 1),
- ];
- };
- OIMO.TetraShape.prototype = Object.create(OIMO.Shape.prototype);
- OIMO.TetraShape.prototype.constructor = OIMO.TetraShape;
- OIMO.TetraShape.prototype.calculateMassInfo = function () {
- // I guess you could calculate box mass and split it
- // in half for the tetra...
- };
- OIMO.TetraShape.prototype.updateProxy = function () {
- this.aabb.setFromPoints(this.verts);
- if (this.proxy !== null)
- this.proxy.update();
- };
- function mtri(a, b, c) {
- return { a: a, b: b, c: c };
- }
- OIMO.CollisionDetector = function () {
- this.flip = false;
- };
- OIMO.CollisionDetector.prototype = {
- constructor: OIMO.CollisionDetector,
- detectCollision: function (shape1, shape2, manifold) {
- OIMO.Error("CollisionDetector", "Inheritance error.");
- }
- };
- /**
- * A collision detector which detects collisions between two boxes.
- * @author saharan
- */
- OIMO.BoxBoxCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- this.clipVertices1 = new OIMO_ARRAY_TYPE(24); // 8 vertices x,y,z
- this.clipVertices2 = new OIMO_ARRAY_TYPE(24);
- this.used = new OIMO_ARRAY_TYPE(8);
- this.INF = 1 / 0;
- };
- OIMO.BoxBoxCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.BoxBoxCollisionDetector.prototype.constructor = OIMO.BoxBoxCollisionDetector;
- OIMO.BoxBoxCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- // What you are doing
- // · I to prepare a separate axis of the fifteen
- //-Six in each of three normal vectors of the xyz direction of the box both
- // · Remaining nine 3x3 a vector perpendicular to the side of the box 2 and the side of the box 1
- // · Calculate the depth to the separation axis
- // Calculates the distance using the inner product and put the amount of embedment
- // · However a vertical separation axis and side to weight a little to avoid vibration
- // And end when there is a separate axis that is remote even one
- // · I look for separation axis with little to dent most
- // Men and if separation axis of the first six - end collision
- // Heng If it separate axis of nine other - side collision
- // Heng - case of a side collision
- // · Find points of two sides on which you made the separation axis
- // Calculates the point of closest approach of a straight line consisting of separate axis points obtained, and the collision point
- //-Surface - the case of the plane crash
- //-Box A, box B and the other a box of better made a separate axis
- // • The surface A and the plane that made the separation axis of the box A, and B to the surface the face of the box B close in the opposite direction to the most isolated axis
- // When viewed from the front surface A, and the cut part exceeding the area of the surface A is a surface B
- //-Plane B becomes the 3-8 triangle, I a candidate for the collision point the vertex of surface B
- // • If more than one candidate 5 exists, scraping up to four
- // For potential collision points of all, to examine the distance between the surface A
- // • If you were on the inside surface of A, and the collision point
- var b1;
- var b2;
- if (shape1.id < shape2.id) {
- b1 = (shape1);
- b2 = (shape2);
- } else {
- b1 = (shape2);
- b2 = (shape1);
- }
- var V1 = b1.elements;
- var V2 = b2.elements;
- var D1 = b1.dimentions;
- var D2 = b2.dimentions;
- var p1 = b1.position;
- var p2 = b2.position;
- var p1x = p1.x;
- var p1y = p1.y;
- var p1z = p1.z;
- var p2x = p2.x;
- var p2y = p2.y;
- var p2z = p2.z;
- // diff
- var dx = p2x - p1x;
- var dy = p2y - p1y;
- var dz = p2z - p1z;
- // distance
- var w1 = b1.halfWidth;
- var h1 = b1.halfHeight;
- var d1 = b1.halfDepth;
- var w2 = b2.halfWidth;
- var h2 = b2.halfHeight;
- var d2 = b2.halfDepth;
- // direction
- // ----------------------------
- // 15 separating axes
- // 1~6: face
- // 7~f: edge
- // http://marupeke296.com/COL_3D_No13_OBBvsOBB.html
- // ----------------------------
- var a1x = D1[0];
- var a1y = D1[1];
- var a1z = D1[2];
- var a2x = D1[3];
- var a2y = D1[4];
- var a2z = D1[5];
- var a3x = D1[6];
- var a3y = D1[7];
- var a3z = D1[8];
- var d1x = D1[9];
- var d1y = D1[10];
- var d1z = D1[11];
- var d2x = D1[12];
- var d2y = D1[13];
- var d2z = D1[14];
- var d3x = D1[15];
- var d3y = D1[16];
- var d3z = D1[17];
- var a4x = D2[0];
- var a4y = D2[1];
- var a4z = D2[2];
- var a5x = D2[3];
- var a5y = D2[4];
- var a5z = D2[5];
- var a6x = D2[6];
- var a6y = D2[7];
- var a6z = D2[8];
- var d4x = D2[9];
- var d4y = D2[10];
- var d4z = D2[11];
- var d5x = D2[12];
- var d5y = D2[13];
- var d5z = D2[14];
- var d6x = D2[15];
- var d6y = D2[16];
- var d6z = D2[17];
- var a7x = a1y * a4z - a1z * a4y;
- var a7y = a1z * a4x - a1x * a4z;
- var a7z = a1x * a4y - a1y * a4x;
- var a8x = a1y * a5z - a1z * a5y;
- var a8y = a1z * a5x - a1x * a5z;
- var a8z = a1x * a5y - a1y * a5x;
- var a9x = a1y * a6z - a1z * a6y;
- var a9y = a1z * a6x - a1x * a6z;
- var a9z = a1x * a6y - a1y * a6x;
- var aax = a2y * a4z - a2z * a4y;
- var aay = a2z * a4x - a2x * a4z;
- var aaz = a2x * a4y - a2y * a4x;
- var abx = a2y * a5z - a2z * a5y;
- var aby = a2z * a5x - a2x * a5z;
- var abz = a2x * a5y - a2y * a5x;
- var acx = a2y * a6z - a2z * a6y;
- var acy = a2z * a6x - a2x * a6z;
- var acz = a2x * a6y - a2y * a6x;
- var adx = a3y * a4z - a3z * a4y;
- var ady = a3z * a4x - a3x * a4z;
- var adz = a3x * a4y - a3y * a4x;
- var aex = a3y * a5z - a3z * a5y;
- var aey = a3z * a5x - a3x * a5z;
- var aez = a3x * a5y - a3y * a5x;
- var afx = a3y * a6z - a3z * a6y;
- var afy = a3z * a6x - a3x * a6z;
- var afz = a3x * a6y - a3y * a6x;
- // right or left flags
- var right1;
- var right2;
- var right3;
- var right4;
- var right5;
- var right6;
- var right7;
- var right8;
- var right9;
- var righta;
- var rightb;
- var rightc;
- var rightd;
- var righte;
- var rightf;
- // overlapping distances
- var overlap1;
- var overlap2;
- var overlap3;
- var overlap4;
- var overlap5;
- var overlap6;
- var overlap7;
- var overlap8;
- var overlap9;
- var overlapa;
- var overlapb;
- var overlapc;
- var overlapd;
- var overlape;
- var overlapf;
- // invalid flags
- var invalid7 = false;
- var invalid8 = false;
- var invalid9 = false;
- var invalida = false;
- var invalidb = false;
- var invalidc = false;
- var invalidd = false;
- var invalide = false;
- var invalidf = false;
- // temporary variables
- var len;
- var len1;
- var len2;
- var dot1;
- var dot2;
- var dot3;
- // try axis 1
- len = a1x * dx + a1y * dy + a1z * dz;
- right1 = len > 0;
- if (!right1) len = -len;
- len1 = w1;
- dot1 = a1x * a4x + a1y * a4y + a1z * a4z;
- dot2 = a1x * a5x + a1y * a5y + a1z * a5z;
- dot3 = a1x * a6x + a1y * a6y + a1z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap1 = len - len1 - len2;
- if (overlap1 > 0) return;
- // try axis 2
- len = a2x * dx + a2y * dy + a2z * dz;
- right2 = len > 0;
- if (!right2) len = -len;
- len1 = h1;
- dot1 = a2x * a4x + a2y * a4y + a2z * a4z;
- dot2 = a2x * a5x + a2y * a5y + a2z * a5z;
- dot3 = a2x * a6x + a2y * a6y + a2z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap2 = len - len1 - len2;
- if (overlap2 > 0) return;
- // try axis 3
- len = a3x * dx + a3y * dy + a3z * dz;
- right3 = len > 0;
- if (!right3) len = -len;
- len1 = d1;
- dot1 = a3x * a4x + a3y * a4y + a3z * a4z;
- dot2 = a3x * a5x + a3y * a5y + a3z * a5z;
- dot3 = a3x * a6x + a3y * a6y + a3z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len2 = dot1 * w2 + dot2 * h2 + dot3 * d2;
- overlap3 = len - len1 - len2;
- if (overlap3 > 0) return;
- // try axis 4
- len = a4x * dx + a4y * dy + a4z * dz;
- right4 = len > 0;
- if (!right4) len = -len;
- dot1 = a4x * a1x + a4y * a1y + a4z * a1z;
- dot2 = a4x * a2x + a4y * a2y + a4z * a2z;
- dot3 = a4x * a3x + a4y * a3y + a4z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = w2;
- overlap4 = (len - len1 - len2) * 1.0;
- if (overlap4 > 0) return;
- // try axis 5
- len = a5x * dx + a5y * dy + a5z * dz;
- right5 = len > 0;
- if (!right5) len = -len;
- dot1 = a5x * a1x + a5y * a1y + a5z * a1z;
- dot2 = a5x * a2x + a5y * a2y + a5z * a2z;
- dot3 = a5x * a3x + a5y * a3y + a5z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = h2;
- overlap5 = (len - len1 - len2) * 1.0;
- if (overlap5 > 0) return;
- // try axis 6
- len = a6x * dx + a6y * dy + a6z * dz;
- right6 = len > 0;
- if (!right6) len = -len;
- dot1 = a6x * a1x + a6y * a1y + a6z * a1z;
- dot2 = a6x * a2x + a6y * a2y + a6z * a2z;
- dot3 = a6x * a3x + a6y * a3y + a6z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- if (dot3 < 0) dot3 = -dot3;
- len1 = dot1 * w1 + dot2 * h1 + dot3 * d1;
- len2 = d2;
- overlap6 = (len - len1 - len2) * 1.0;
- if (overlap6 > 0) return;
- // try axis 7
- len = a7x * a7x + a7y * a7y + a7z * a7z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a7x *= len;
- a7y *= len;
- a7z *= len;
- len = a7x * dx + a7y * dy + a7z * dz;
- right7 = len > 0;
- if (!right7) len = -len;
- dot1 = a7x * a2x + a7y * a2y + a7z * a2z;
- dot2 = a7x * a3x + a7y * a3y + a7z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a7x * a5x + a7y * a5y + a7z * a5z;
- dot2 = a7x * a6x + a7y * a6y + a7z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlap7 = len - len1 - len2;
- if (overlap7 > 0) return;
- } else {
- right7 = false;
- overlap7 = 0;
- invalid7 = true;
- }
- // try axis 8
- len = a8x * a8x + a8y * a8y + a8z * a8z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a8x *= len;
- a8y *= len;
- a8z *= len;
- len = a8x * dx + a8y * dy + a8z * dz;
- right8 = len > 0;
- if (!right8) len = -len;
- dot1 = a8x * a2x + a8y * a2y + a8z * a2z;
- dot2 = a8x * a3x + a8y * a3y + a8z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a8x * a4x + a8y * a4y + a8z * a4z;
- dot2 = a8x * a6x + a8y * a6y + a8z * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlap8 = len - len1 - len2;
- if (overlap8 > 0) return;
- } else {
- right8 = false;
- overlap8 = 0;
- invalid8 = true;
- }
- // try axis 9
- len = a9x * a9x + a9y * a9y + a9z * a9z;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- a9x *= len;
- a9y *= len;
- a9z *= len;
- len = a9x * dx + a9y * dy + a9z * dz;
- right9 = len > 0;
- if (!right9) len = -len;
- dot1 = a9x * a2x + a9y * a2y + a9z * a2z;
- dot2 = a9x * a3x + a9y * a3y + a9z * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * h1 + dot2 * d1;
- dot1 = a9x * a4x + a9y * a4y + a9z * a4z;
- dot2 = a9x * a5x + a9y * a5y + a9z * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlap9 = len - len1 - len2;
- if (overlap9 > 0) return;
- } else {
- right9 = false;
- overlap9 = 0;
- invalid9 = true;
- }
- // try axis 10
- len = aax * aax + aay * aay + aaz * aaz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- aax *= len;
- aay *= len;
- aaz *= len;
- len = aax * dx + aay * dy + aaz * dz;
- righta = len > 0;
- if (!righta) len = -len;
- dot1 = aax * a1x + aay * a1y + aaz * a1z;
- dot2 = aax * a3x + aay * a3y + aaz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = aax * a5x + aay * a5y + aaz * a5z;
- dot2 = aax * a6x + aay * a6y + aaz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlapa = len - len1 - len2;
- if (overlapa > 0) return;
- } else {
- righta = false;
- overlapa = 0;
- invalida = true;
- }
- // try axis 11
- len = abx * abx + aby * aby + abz * abz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- abx *= len;
- aby *= len;
- abz *= len;
- len = abx * dx + aby * dy + abz * dz;
- rightb = len > 0;
- if (!rightb) len = -len;
- dot1 = abx * a1x + aby * a1y + abz * a1z;
- dot2 = abx * a3x + aby * a3y + abz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = abx * a4x + aby * a4y + abz * a4z;
- dot2 = abx * a6x + aby * a6y + abz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlapb = len - len1 - len2;
- if (overlapb > 0) return;
- } else {
- rightb = false;
- overlapb = 0;
- invalidb = true;
- }
- // try axis 12
- len = acx * acx + acy * acy + acz * acz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- acx *= len;
- acy *= len;
- acz *= len;
- len = acx * dx + acy * dy + acz * dz;
- rightc = len > 0;
- if (!rightc) len = -len;
- dot1 = acx * a1x + acy * a1y + acz * a1z;
- dot2 = acx * a3x + acy * a3y + acz * a3z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * d1;
- dot1 = acx * a4x + acy * a4y + acz * a4z;
- dot2 = acx * a5x + acy * a5y + acz * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlapc = len - len1 - len2;
- if (overlapc > 0) return;
- } else {
- rightc = false;
- overlapc = 0;
- invalidc = true;
- }
- // try axis 13
- len = adx * adx + ady * ady + adz * adz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- adx *= len;
- ady *= len;
- adz *= len;
- len = adx * dx + ady * dy + adz * dz;
- rightd = len > 0;
- if (!rightd) len = -len;
- dot1 = adx * a1x + ady * a1y + adz * a1z;
- dot2 = adx * a2x + ady * a2y + adz * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = adx * a5x + ady * a5y + adz * a5z;
- dot2 = adx * a6x + ady * a6y + adz * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * h2 + dot2 * d2;
- overlapd = len - len1 - len2;
- if (overlapd > 0) return;
- } else {
- rightd = false;
- overlapd = 0;
- invalidd = true;
- }
- // try axis 14
- len = aex * aex + aey * aey + aez * aez;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- aex *= len;
- aey *= len;
- aez *= len;
- len = aex * dx + aey * dy + aez * dz;
- righte = len > 0;
- if (!righte) len = -len;
- dot1 = aex * a1x + aey * a1y + aez * a1z;
- dot2 = aex * a2x + aey * a2y + aez * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = aex * a4x + aey * a4y + aez * a4z;
- dot2 = aex * a6x + aey * a6y + aez * a6z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * d2;
- overlape = len - len1 - len2;
- if (overlape > 0) return;
- } else {
- righte = false;
- overlape = 0;
- invalide = true;
- }
- // try axis 15
- len = afx * afx + afy * afy + afz * afz;
- if (len > 1e-5) {
- len = 1 / OIMO.sqrt(len);
- afx *= len;
- afy *= len;
- afz *= len;
- len = afx * dx + afy * dy + afz * dz;
- rightf = len > 0;
- if (!rightf) len = -len;
- dot1 = afx * a1x + afy * a1y + afz * a1z;
- dot2 = afx * a2x + afy * a2y + afz * a2z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len1 = dot1 * w1 + dot2 * h1;
- dot1 = afx * a4x + afy * a4y + afz * a4z;
- dot2 = afx * a5x + afy * a5y + afz * a5z;
- if (dot1 < 0) dot1 = -dot1;
- if (dot2 < 0) dot2 = -dot2;
- len2 = dot1 * w2 + dot2 * h2;
- overlapf = len - len1 - len2;
- if (overlapf > 0) return;
- } else {
- rightf = false;
- overlapf = 0;
- invalidf = true;
- }
- // boxes are overlapping
- var depth = overlap1;
- var depth2 = overlap1;
- var minIndex = 0;
- var right = right1;
- if (overlap2 > depth2) {
- depth = overlap2;
- depth2 = overlap2;
- minIndex = 1;
- right = right2;
- }
- if (overlap3 > depth2) {
- depth = overlap3;
- depth2 = overlap3;
- minIndex = 2;
- right = right3;
- }
- if (overlap4 > depth2) {
- depth = overlap4;
- depth2 = overlap4;
- minIndex = 3;
- right = right4;
- }
- if (overlap5 > depth2) {
- depth = overlap5;
- depth2 = overlap5;
- minIndex = 4;
- right = right5;
- }
- if (overlap6 > depth2) {
- depth = overlap6;
- depth2 = overlap6;
- minIndex = 5;
- right = right6;
- }
- if (overlap7 - 0.01 > depth2 && !invalid7) {
- depth = overlap7;
- depth2 = overlap7 - 0.01;
- minIndex = 6;
- right = right7;
- }
- if (overlap8 - 0.01 > depth2 && !invalid8) {
- depth = overlap8;
- depth2 = overlap8 - 0.01;
- minIndex = 7;
- right = right8;
- }
- if (overlap9 - 0.01 > depth2 && !invalid9) {
- depth = overlap9;
- depth2 = overlap9 - 0.01;
- minIndex = 8;
- right = right9;
- }
- if (overlapa - 0.01 > depth2 && !invalida) {
- depth = overlapa;
- depth2 = overlapa - 0.01;
- minIndex = 9;
- right = righta;
- }
- if (overlapb - 0.01 > depth2 && !invalidb) {
- depth = overlapb;
- depth2 = overlapb - 0.01;
- minIndex = 10;
- right = rightb;
- }
- if (overlapc - 0.01 > depth2 && !invalidc) {
- depth = overlapc;
- depth2 = overlapc - 0.01;
- minIndex = 11;
- right = rightc;
- }
- if (overlapd - 0.01 > depth2 && !invalidd) {
- depth = overlapd;
- depth2 = overlapd - 0.01;
- minIndex = 12;
- right = rightd;
- }
- if (overlape - 0.01 > depth2 && !invalide) {
- depth = overlape;
- depth2 = overlape - 0.01;
- minIndex = 13;
- right = righte;
- }
- if (overlapf - 0.01 > depth2 && !invalidf) {
- depth = overlapf;
- minIndex = 14;
- right = rightf;
- }
- // normal
- var nx = 0;
- var ny = 0;
- var nz = 0;
- // edge line or face side normal
- var n1x = 0;
- var n1y = 0;
- var n1z = 0;
- var n2x = 0;
- var n2y = 0;
- var n2z = 0;
- // center of current face
- var cx = 0;
- var cy = 0;
- var cz = 0;
- // face side
- var s1x = 0;
- var s1y = 0;
- var s1z = 0;
- var s2x = 0;
- var s2y = 0;
- var s2z = 0;
- // swap b1 b2
- var swap = false;
- //_______________________________________
- if (minIndex == 0) {// b1.x * b2
- if (right) {
- cx = p1x + d1x; cy = p1y + d1y; cz = p1z + d1z;
- nx = a1x; ny = a1y; nz = a1z;
- } else {
- cx = p1x - d1x; cy = p1y - d1y; cz = p1z - d1z;
- nx = -a1x; ny = -a1y; nz = -a1z;
- }
- s1x = d2x; s1y = d2y; s1z = d2z;
- n1x = -a2x; n1y = -a2y; n1z = -a2z;
- s2x = d3x; s2y = d3y; s2z = d3z;
- n2x = -a3x; n2y = -a3y; n2z = -a3z;
- }
- else if (minIndex == 1) {// b1.y * b2
- if (right) {
- cx = p1x + d2x; cy = p1y + d2y; cz = p1z + d2z;
- nx = a2x; ny = a2y; nz = a2z;
- } else {
- cx = p1x - d2x; cy = p1y - d2y; cz = p1z - d2z;
- nx = -a2x; ny = -a2y; nz = -a2z;
- }
- s1x = d1x; s1y = d1y; s1z = d1z;
- n1x = -a1x; n1y = -a1y; n1z = -a1z;
- s2x = d3x; s2y = d3y; s2z = d3z;
- n2x = -a3x; n2y = -a3y; n2z = -a3z;
- }
- else if (minIndex == 2) {// b1.z * b2
- if (right) {
- cx = p1x + d3x; cy = p1y + d3y; cz = p1z + d3z;
- nx = a3x; ny = a3y; nz = a3z;
- } else {
- cx = p1x - d3x; cy = p1y - d3y; cz = p1z - d3z;
- nx = -a3x; ny = -a3y; nz = -a3z;
- }
- s1x = d1x; s1y = d1y; s1z = d1z;
- n1x = -a1x; n1y = -a1y; n1z = -a1z;
- s2x = d2x; s2y = d2y; s2z = d2z;
- n2x = -a2x; n2y = -a2y; n2z = -a2z;
- }
- else if (minIndex == 3) {// b2.x * b1
- swap = true;
- if (!right) {
- cx = p2x + d4x; cy = p2y + d4y; cz = p2z + d4z;
- nx = a4x; ny = a4y; nz = a4z;
- } else {
- cx = p2x - d4x; cy = p2y - d4y; cz = p2z - d4z;
- nx = -a4x; ny = -a4y; nz = -a4z;
- }
- s1x = d5x; s1y = d5y; s1z = d5z;
- n1x = -a5x; n1y = -a5y; n1z = -a5z;
- s2x = d6x; s2y = d6y; s2z = d6z;
- n2x = -a6x; n2y = -a6y; n2z = -a6z;
- }
- else if (minIndex == 4) {// b2.y * b1
- swap = true;
- if (!right) {
- cx = p2x + d5x; cy = p2y + d5y; cz = p2z + d5z;
- nx = a5x; ny = a5y; nz = a5z;
- } else {
- cx = p2x - d5x; cy = p2y - d5y; cz = p2z - d5z;
- nx = -a5x; ny = -a5y; nz = -a5z;
- }
- s1x = d4x; s1y = d4y; s1z = d4z;
- n1x = -a4x; n1y = -a4y; n1z = -a4z;
- s2x = d6x; s2y = d6y; s2z = d6z;
- n2x = -a6x; n2y = -a6y; n2z = -a6z;
- }
- else if (minIndex == 5) {// b2.z * b1
- swap = true;
- if (!right) {
- cx = p2x + d6x; cy = p2y + d6y; cz = p2z + d6z;
- nx = a6x; ny = a6y; nz = a6z;
- } else {
- cx = p2x - d6x; cy = p2y - d6y; cz = p2z - d6z;
- nx = -a6x; ny = -a6y; nz = -a6z;
- }
- s1x = d4x; s1y = d4y; s1z = d4z;
- n1x = -a4x; n1y = -a4y; n1z = -a4z;
- s2x = d5x; s2y = d5y; s2z = d5z;
- n2x = -a5x; n2y = -a5y; n2z = -a5z;
- }
- else if (minIndex == 6) {// b1.x * b2.x
- nx = a7x; ny = a7y; nz = a7z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a4x; n2y = a4y; n2z = a4z;
- }
- else if (minIndex == 7) {// b1.x * b2.y
- nx = a8x; ny = a8y; nz = a8z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 8) {// b1.x * b2.z
- nx = a9x; ny = a9y; nz = a9z;
- n1x = a1x; n1y = a1y; n1z = a1z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- else if (minIndex == 9) {// b1.y * b2.x
- nx = aax; ny = aay; nz = aaz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a4x; n2y = a4y; n2z = a4z
- }
- else if (minIndex == 10) {// b1.y * b2.y
- nx = abx; ny = aby; nz = abz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 11) {// b1.y * b2.z
- nx = acx; ny = acy; nz = acz;
- n1x = a2x; n1y = a2y; n1z = a2z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- else if (minIndex == 12) {// b1.z * b2.x
- nx = adx; ny = ady; nz = adz;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a4x; n2y = a4y; n2z = a4z;
- }
- else if (minIndex == 13) {// b1.z * b2.y
- nx = aex; ny = aey; nz = aez;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a5x; n2y = a5y; n2z = a5z;
- }
- else if (minIndex == 14) {// b1.z * b2.z
- nx = afx; ny = afy; nz = afz;
- n1x = a3x; n1y = a3y; n1z = a3z;
- n2x = a6x; n2y = a6y; n2z = a6z;
- }
- //__________________________________________
- var v;
- if (minIndex > 5) {
- if (!right) {
- nx = -nx; ny = -ny; nz = -nz;
- }
- var distance;
- var maxDistance;
- var vx;
- var vy;
- var vz;
- var v1x;
- var v1y;
- var v1z;
- var v2x;
- var v2y;
- var v2z;
- //vertex1;
- v1x = V1[0]; v1y = V1[1]; v1z = V1[2];
- maxDistance = nx * v1x + ny * v1y + nz * v1z;
- //vertex2;
- vx = V1[3]; vy = V1[4]; vz = V1[5];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex3;
- vx = V1[6]; vy = V1[7]; vz = V1[8];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex4;
- vx = V1[9]; vy = V1[10]; vz = V1[11];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex5;
- vx = V1[12]; vy = V1[13]; vz = V1[14];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex6;
- vx = V1[15]; vy = V1[16]; vz = V1[17];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex7;
- vx = V1[18]; vy = V1[19]; vz = V1[20];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex8;
- vx = V1[21]; vy = V1[22]; vz = V1[23];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance > maxDistance) {
- maxDistance = distance;
- v1x = vx; v1y = vy; v1z = vz;
- }
- //vertex1;
- v2x = V2[0]; v2y = V2[1]; v2z = V2[2];
- maxDistance = nx * v2x + ny * v2y + nz * v2z;
- //vertex2;
- vx = V2[3]; vy = V2[4]; vz = V2[5];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex3;
- vx = V2[6]; vy = V2[7]; vz = V2[8];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex4;
- vx = V2[9]; vy = V2[10]; vz = V2[11];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex5;
- vx = V2[12]; vy = V2[13]; vz = V2[14];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex6;
- vx = V2[15]; vy = V2[16]; vz = V2[17];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex7;
- vx = V2[18]; vy = V2[19]; vz = V2[20];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- //vertex8;
- vx = V2[21]; vy = V2[22]; vz = V2[23];
- distance = nx * vx + ny * vy + nz * vz;
- if (distance < maxDistance) {
- maxDistance = distance;
- v2x = vx; v2y = vy; v2z = vz;
- }
- vx = v2x - v1x; vy = v2y - v1y; vz = v2z - v1z;
- dot1 = n1x * n2x + n1y * n2y + n1z * n2z;
- var t = (vx * (n1x - n2x * dot1) + vy * (n1y - n2y * dot1) + vz * (n1z - n2z * dot1)) / (1 - dot1 * dot1);
- manifold.addPoint(v1x + n1x * t + nx * depth * 0.5, v1y + n1y * t + ny * depth * 0.5, v1z + n1z * t + nz * depth * 0.5, nx, ny, nz, depth, false);
- return;
- }
- // now detect face-face collision...
- // target quad
- var q1x;
- var q1y;
- var q1z;
- var q2x;
- var q2y;
- var q2z;
- var q3x;
- var q3y;
- var q3z;
- var q4x;
- var q4y;
- var q4z;
- // search support face and vertex
- var minDot = 1;
- var dot = 0;
- var minDotIndex = 0;
- if (swap) {
- dot = a1x * nx + a1y * ny + a1z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 0;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 1;
- }
- dot = a2x * nx + a2y * ny + a2z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 2;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 3;
- }
- dot = a3x * nx + a3y * ny + a3z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 4;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 5;
- }
- if (minDotIndex == 0) {// x+ face
- q1x = V1[0]; q1y = V1[1]; q1z = V1[2];//vertex1
- q2x = V1[6]; q2y = V1[7]; q2z = V1[8];//vertex3
- q3x = V1[9]; q3y = V1[10]; q3z = V1[11];//vertex4
- q4x = V1[3]; q4y = V1[4]; q4z = V1[5];//vertex2
- }
- else if (minDotIndex == 1) {// x- face
- q1x = V1[15]; q1y = V1[16]; q1z = V1[17];//vertex6
- q2x = V1[21]; q2y = V1[22]; q2z = V1[23];//vertex8
- q3x = V1[18]; q3y = V1[19]; q3z = V1[20];//vertex7
- q4x = V1[12]; q4y = V1[13]; q4z = V1[14];//vertex5
- }
- else if (minDotIndex == 2) {// y+ face
- q1x = V1[12]; q1y = V1[13]; q1z = V1[14];//vertex5
- q2x = V1[0]; q2y = V1[1]; q2z = V1[2];//vertex1
- q3x = V1[3]; q3y = V1[4]; q3z = V1[5];//vertex2
- q4x = V1[15]; q4y = V1[16]; q4z = V1[17];//vertex6
- }
- else if (minDotIndex == 3) {// y- face
- q1x = V1[21]; q1y = V1[22]; q1z = V1[23];//vertex8
- q2x = V1[9]; q2y = V1[10]; q2z = V1[11];//vertex4
- q3x = V1[6]; q3y = V1[7]; q3z = V1[8];//vertex3
- q4x = V1[18]; q4y = V1[19]; q4z = V1[20];//vertex7
- }
- else if (minDotIndex == 4) {// z+ face
- q1x = V1[12]; q1y = V1[13]; q1z = V1[14];//vertex5
- q2x = V1[18]; q2y = V1[19]; q2z = V1[20];//vertex7
- q3x = V1[6]; q3y = V1[7]; q3z = V1[8];//vertex3
- q4x = V1[0]; q4y = V1[1]; q4z = V1[2];//vertex1
- }
- else if (minDotIndex == 5) {// z- face
- q1x = V1[3]; q1y = V1[4]; q1z = V1[5];//vertex2
- q2x = V1[6]; q2y = V1[7]; q2z = V1[8];//vertex4
- q3x = V1[21]; q3y = V1[22]; q3z = V1[23];//vertex8
- q4x = V1[15]; q4y = V1[16]; q4z = V1[17];//vertex6
- }
- } else {
- dot = a4x * nx + a4y * ny + a4z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 0;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 1;
- }
- dot = a5x * nx + a5y * ny + a5z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 2;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 3;
- }
- dot = a6x * nx + a6y * ny + a6z * nz;
- if (dot < minDot) {
- minDot = dot;
- minDotIndex = 4;
- }
- if (-dot < minDot) {
- minDot = -dot;
- minDotIndex = 5;
- }
- //______________________________________________________
- if (minDotIndex == 0) {// x+ face
- q1x = V2[0]; q1y = V2[1]; q1z = V2[2];//vertex1
- q2x = V2[6]; q2y = V2[7]; q2z = V2[8];//vertex3
- q3x = V2[9]; q3y = V2[10]; q3z = V2[11];//vertex4
- q4x = V2[3]; q4y = V2[4]; q4z = V2[5];//vertex2
- }
- else if (minDotIndex == 1) {// x- face
- q1x = V2[15]; q1y = V2[16]; q1z = V2[17];//vertex6
- q2x = V2[21]; q2y = V2[22]; q2z = V2[23]; //vertex8
- q3x = V2[18]; q3y = V2[19]; q3z = V2[20];//vertex7
- q4x = V2[12]; q4y = V2[13]; q4z = V2[14];//vertex5
- }
- else if (minDotIndex == 2) {// y+ face
- q1x = V2[12]; q1y = V2[13]; q1z = V2[14];//vertex5
- q2x = V2[0]; q2y = V2[1]; q2z = V2[2];//vertex1
- q3x = V2[3]; q3y = V2[4]; q3z = V2[5];//vertex2
- q4x = V2[15]; q4y = V2[16]; q4z = V2[17];//vertex6
- }
- else if (minDotIndex == 3) {// y- face
- q1x = V2[21]; q1y = V2[22]; q1z = V2[23];//vertex8
- q2x = V2[9]; q2y = V2[10]; q2z = V2[11];//vertex4
- q3x = V2[6]; q3y = V2[7]; q3z = V2[8];//vertex3
- q4x = V2[18]; q4y = V2[19]; q4z = V2[20];//vertex7
- }
- else if (minDotIndex == 4) {// z+ face
- q1x = V2[12]; q1y = V2[13]; q1z = V2[14];//vertex5
- q2x = V2[18]; q2y = V2[19]; q2z = V2[20];//vertex7
- q3x = V2[6]; q3y = V2[7]; q3z = V2[8];//vertex3
- q4x = V2[0]; q4y = V2[1]; q4z = V2[2];//vertex1
- }
- else if (minDotIndex == 5) {// z- face
- q1x = V2[3]; q1y = V2[4]; q1z = V2[5];//vertex2
- q2x = V2[9]; q2y = V2[10]; q2z = V2[11];//vertex4
- q3x = V2[21]; q3y = V2[22]; q3z = V2[23];//vertex8
- q4x = V2[15]; q4y = V2[16]; q4z = V2[17];//vertex6
- }
- }
- // clip vertices
- var numClipVertices;
- var numAddedClipVertices;
- var index;
- var x1;
- var y1;
- var z1;
- var x2;
- var y2;
- var z2;
- this.clipVertices1[0] = q1x;
- this.clipVertices1[1] = q1y;
- this.clipVertices1[2] = q1z;
- this.clipVertices1[3] = q2x;
- this.clipVertices1[4] = q2y;
- this.clipVertices1[5] = q2z;
- this.clipVertices1[6] = q3x;
- this.clipVertices1[7] = q3y;
- this.clipVertices1[8] = q3z;
- this.clipVertices1[9] = q4x;
- this.clipVertices1[10] = q4y;
- this.clipVertices1[11] = q4z;
- numAddedClipVertices = 0;
- x1 = this.clipVertices1[9];
- y1 = this.clipVertices1[10];
- z1 = this.clipVertices1[11];
- dot1 = (x1 - cx - s1x) * n1x + (y1 - cy - s1y) * n1y + (z1 - cz - s1z) * n1z;
- //var i = 4;
- //while(i--){
- for (var i = 0; i < 4; i++) {
- index = i * 3;
- x2 = this.clipVertices1[index];
- y2 = this.clipVertices1[index + 1];
- z2 = this.clipVertices1[index + 2];
- dot2 = (x2 - cx - s1x) * n1x + (y2 - cy - s1y) * n1y + (z2 - cz - s1z) * n1z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices2[index];
- y1 = this.clipVertices2[index + 1];
- z1 = this.clipVertices2[index + 2];
- dot1 = (x1 - cx - s2x) * n2x + (y1 - cy - s2y) * n2y + (z1 - cz - s2z) * n2z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices2[index];
- y2 = this.clipVertices2[index + 1];
- z2 = this.clipVertices2[index + 2];
- dot2 = (x2 - cx - s2x) * n2x + (y2 - cy - s2y) * n2y + (z2 - cz - s2z) * n2z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot1 = (x1 - cx + s1x) * -n1x + (y1 - cy + s1y) * -n1y + (z1 - cz + s1z) * -n1z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices1[index];
- y2 = this.clipVertices1[index + 1];
- z2 = this.clipVertices1[index + 2];
- dot2 = (x2 - cx + s1x) * -n1x + (y2 - cy + s1y) * -n1y + (z2 - cz + s1z) * -n1z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices2[index] = x1 + (x2 - x1) * t;
- this.clipVertices2[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices2[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices2[index] = x2;
- this.clipVertices2[index + 1] = y2;
- this.clipVertices2[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (numClipVertices == 0) return;
- numAddedClipVertices = 0;
- index = (numClipVertices - 1) * 3;
- x1 = this.clipVertices2[index];
- y1 = this.clipVertices2[index + 1];
- z1 = this.clipVertices2[index + 2];
- dot1 = (x1 - cx + s2x) * -n2x + (y1 - cy + s2y) * -n2y + (z1 - cz + s2z) * -n2z;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x2 = this.clipVertices2[index];
- y2 = this.clipVertices2[index + 1];
- z2 = this.clipVertices2[index + 2];
- dot2 = (x2 - cx + s2x) * -n2x + (y2 - cy + s2y) * -n2y + (z2 - cz + s2z) * -n2z;
- if (dot1 > 0) {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- } else {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- }
- } else {
- if (dot2 > 0) {
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- t = dot1 / (dot1 - dot2);
- this.clipVertices1[index] = x1 + (x2 - x1) * t;
- this.clipVertices1[index + 1] = y1 + (y2 - y1) * t;
- this.clipVertices1[index + 2] = z1 + (z2 - z1) * t;
- index = numAddedClipVertices * 3;
- numAddedClipVertices++;
- this.clipVertices1[index] = x2;
- this.clipVertices1[index + 1] = y2;
- this.clipVertices1[index + 2] = z2;
- }
- }
- x1 = x2;
- y1 = y2;
- z1 = z2;
- dot1 = dot2;
- }
- numClipVertices = numAddedClipVertices;
- if (swap) {
- var tb = b1;
- b1 = b2;
- b2 = tb;
- }
- if (numClipVertices == 0) return;
- var flipped = b1 != shape1;
- if (numClipVertices > 4) {
- x1 = (q1x + q2x + q3x + q4x) * 0.25;
- y1 = (q1y + q2y + q3y + q4y) * 0.25;
- z1 = (q1z + q2z + q3z + q4z) * 0.25;
- n1x = q1x - x1;
- n1y = q1y - y1;
- n1z = q1z - z1;
- n2x = q2x - x1;
- n2y = q2y - y1;
- n2z = q2z - z1;
- var index1 = 0;
- var index2 = 0;
- var index3 = 0;
- var index4 = 0;
- var maxDot = -this.INF;
- minDot = this.INF;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- this.used[i] = false;
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = x1 * n1x + y1 * n1y + z1 * n1z;
- if (dot < minDot) {
- minDot = dot;
- index1 = i;
- }
- if (dot > maxDot) {
- maxDot = dot;
- index3 = i;
- }
- }
- this.used[index1] = true;
- this.used[index3] = true;
- maxDot = -this.INF;
- minDot = this.INF;
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- if (this.used[i]) continue;
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = x1 * n2x + y1 * n2y + z1 * n2z;
- if (dot < minDot) {
- minDot = dot;
- index2 = i;
- }
- if (dot > maxDot) {
- maxDot = dot;
- index4 = i;
- }
- }
- index = index1 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index2 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index3 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- index = index4 * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- } else {
- //i = numClipVertices;
- //while(i--){
- for (i = 0; i < numClipVertices; i++) {
- index = i * 3;
- x1 = this.clipVertices1[index];
- y1 = this.clipVertices1[index + 1];
- z1 = this.clipVertices1[index + 2];
- dot = (x1 - cx) * nx + (y1 - cy) * ny + (z1 - cz) * nz;
- if (dot < 0) manifold.addPoint(x1, y1, z1, nx, ny, nz, dot, flipped);
- }
- }
- };
- /**
- * A collision detector which detects collisions between sphere and box.
- * @author saharan
- */
- OIMO.SphereBoxCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.SphereBoxCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereBoxCollisionDetector.prototype.constructor = OIMO.SphereBoxCollisionDetector;
- OIMO.SphereBoxCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s;
- var b;
- if (this.flip) {
- s = (shape2);
- b = (shape1);
- } else {
- s = (shape1);
- b = (shape2);
- }
- var D = b.dimentions;
- var ps = s.position;
- var psx = ps.x;
- var psy = ps.y;
- var psz = ps.z;
- var pb = b.position;
- var pbx = pb.x;
- var pby = pb.y;
- var pbz = pb.z;
- var rad = s.radius;
- var hw = b.halfWidth;
- var hh = b.halfHeight;
- var hd = b.halfDepth;
- var dx = psx - pbx;
- var dy = psy - pby;
- var dz = psz - pbz;
- var sx = D[0] * dx + D[1] * dy + D[2] * dz;
- var sy = D[3] * dx + D[4] * dy + D[5] * dz;
- var sz = D[6] * dx + D[7] * dy + D[8] * dz;
- var cx;
- var cy;
- var cz;
- var len;
- var invLen;
- var overlap = 0;
- if (sx > hw) {
- sx = hw;
- } else if (sx < -hw) {
- sx = -hw;
- } else {
- overlap = 1;
- }
- if (sy > hh) {
- sy = hh;
- } else if (sy < -hh) {
- sy = -hh;
- } else {
- overlap |= 2;
- }
- if (sz > hd) {
- sz = hd;
- } else if (sz < -hd) {
- sz = -hd;
- } else {
- overlap |= 4;
- }
- if (overlap == 7) {
- // center of sphere is in the box
- if (sx < 0) {
- dx = hw + sx;
- } else {
- dx = hw - sx;
- }
- if (sy < 0) {
- dy = hh + sy;
- } else {
- dy = hh - sy;
- }
- if (sz < 0) {
- dz = hd + sz;
- } else {
- dz = hd - sz;
- }
- if (dx < dy) {
- if (dx < dz) {
- len = dx - hw;
- if (sx < 0) {
- sx = -hw;
- dx = D[0];
- dy = D[1];
- dz = D[2];
- } else {
- sx = hw;
- dx = -D[0];
- dy = -D[1];
- dz = -D[2];
- }
- } else {
- len = dz - hd;
- if (sz < 0) {
- sz = -hd;
- dx = D[6];
- dy = D[7];
- dz = D[8];
- } else {
- sz = hd;
- dx = -D[6];
- dy = -D[7];
- dz = -D[8];
- }
- }
- } else {
- if (dy < dz) {
- len = dy - hh;
- if (sy < 0) {
- sy = -hh;
- dx = D[3];
- dy = D[4];
- dz = D[5];
- } else {
- sy = hh;
- dx = -D[3];
- dy = -D[4];
- dz = -D[5];
- }
- } else {
- len = dz - hd;
- if (sz < 0) {
- sz = -hd;
- dx = D[6];
- dy = D[7];
- dz = D[8];
- } else {
- sz = hd;
- dx = -D[6];
- dy = -D[7];
- dz = -D[8];
- }
- }
- }
- cx = pbx + sx * D[0] + sy * D[3] + sz * D[6];
- cy = pby + sx * D[1] + sy * D[4] + sz * D[7];
- cz = pbz + sx * D[2] + sy * D[5] + sz * D[8];
- manifold.addPoint(psx + rad * dx, psy + rad * dy, psz + rad * dz, dx, dy, dz, len - rad, this.flip);
- } else {
- cx = pbx + sx * D[0] + sy * D[3] + sz * D[6];
- cy = pby + sx * D[1] + sy * D[4] + sz * D[7];
- cz = pbz + sx * D[2] + sy * D[5] + sz * D[8];
- dx = cx - ps.x;
- dy = cy - ps.y;
- dz = cz - ps.z;
- len = dx * dx + dy * dy + dz * dz;
- if (len > 0 && len < rad * rad) {
- len = OIMO.sqrt(len);
- invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- manifold.addPoint(psx + rad * dx, psy + rad * dy, psz + rad * dz, dx, dy, dz, len - rad, this.flip);
- }
- }
- };
- /**
- * A collision detector which detects collisions between two spheres.
- * @author saharan
- */
- OIMO.SphereSphereCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.SphereSphereCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereSphereCollisionDetector.prototype.constructor = OIMO.SphereSphereCollisionDetector;
- OIMO.SphereSphereCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s1 = shape1;
- var s2 = shape2;
- var p1 = s1.position;
- var p2 = s2.position;
- var dx = p2.x - p1.x;
- var dy = p2.y - p1.y;
- var dz = p2.z - p1.z;
- var len = dx * dx + dy * dy + dz * dz;
- var r1 = s1.radius;
- var r2 = s2.radius;
- var rad = r1 + r2;
- if (len > 0 && len < rad * rad) {
- len = OIMO.sqrt(len);
- var invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- manifold.addPoint(p1.x + dx * r1, p1.y + dy * r1, p1.z + dz * r1, dx, dy, dz, len - rad, false);
- }
- };
- OIMO.BoxCylinderCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.BoxCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.BoxCylinderCollisionDetector.prototype.constructor = OIMO.BoxCylinderCollisionDetector;
- OIMO.BoxCylinderCollisionDetector.prototype.getSep = function (c1, c2, sep, pos, dep) {
- var t1x;
- var t1y;
- var t1z;
- var t2x;
- var t2y;
- var t2z;
- var sup = new OIMO.Vec3();
- var len;
- var p1x;
- var p1y;
- var p1z;
- var p2x;
- var p2y;
- var p2z;
- var v01x = c1.position.x;
- var v01y = c1.position.y;
- var v01z = c1.position.z;
- var v02x = c2.position.x;
- var v02y = c2.position.y;
- var v02z = c2.position.z;
- var v0x = v02x - v01x;
- var v0y = v02y - v01y;
- var v0z = v02z - v01z;
- if (v0x * v0x + v0y * v0y + v0z * v0z == 0) v0y = 0.001;
- var nx = -v0x;
- var ny = -v0y;
- var nz = -v0z;
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v11x = sup.x;
- var v11y = sup.y;
- var v11z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v12x = sup.x;
- var v12y = sup.y;
- var v12z = sup.z;
- var v1x = v12x - v11x;
- var v1y = v12y - v11y;
- var v1z = v12z - v11z;
- if (v1x * nx + v1y * ny + v1z * nz <= 0) {
- return false;
- }
- nx = v1y * v0z - v1z * v0y;
- ny = v1z * v0x - v1x * v0z;
- nz = v1x * v0y - v1y * v0x;
- if (nx * nx + ny * ny + nz * nz == 0) {
- sep.init(v1x - v0x, v1y - v0y, v1z - v0z);
- sep.normalize(sep);
- pos.init((v11x + v12x) * 0.5, (v11y + v12y) * 0.5, (v11z + v12z) * 0.5);
- return true;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v21x = sup.x;
- var v21y = sup.y;
- var v21z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v22x = sup.x;
- var v22y = sup.y;
- var v22z = sup.z;
- var v2x = v22x - v21x;
- var v2y = v22y - v21y;
- var v2z = v22z - v21z;
- if (v2x * nx + v2y * ny + v2z * nz <= 0) {
- return false;
- }
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- if (nx * v0x + ny * v0y + nz * v0z > 0) {
- t1x = v1x;
- t1y = v1y;
- t1z = v1z;
- v1x = v2x;
- v1y = v2y;
- v1z = v2z;
- v2x = t1x;
- v2y = t1y;
- v2z = t1z;
- t1x = v11x;
- t1y = v11y;
- t1z = v11z;
- v11x = v21x;
- v11y = v21y;
- v11z = v21z;
- v21x = t1x;
- v21y = t1y;
- v21z = t1z;
- t1x = v12x;
- t1y = v12y;
- t1z = v12z;
- v12x = v22x;
- v12y = v22y;
- v12z = v22z;
- v22x = t1x;
- v22y = t1y;
- v22z = t1z;
- nx = -nx;
- ny = -ny;
- nz = -nz;
- }
- var iterations = 0;
- while (true) {
- if (++iterations > 100) {
- return false;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v31x = sup.x;
- var v31y = sup.y;
- var v31z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v32x = sup.x;
- var v32y = sup.y;
- var v32z = sup.z;
- var v3x = v32x - v31x;
- var v3y = v32y - v31y;
- var v3z = v32z - v31z;
- if (v3x * nx + v3y * ny + v3z * nz <= 0) {
- return false;
- }
- if ((v1y * v3z - v1z * v3y) * v0x + (v1z * v3x - v1x * v3z) * v0y + (v1x * v3y - v1y * v3x) * v0z < 0) {
- v2x = v3x;
- v2y = v3y;
- v2z = v3z;
- v21x = v31x;
- v21y = v31y;
- v21z = v31z;
- v22x = v32x;
- v22y = v32y;
- v22z = v32z;
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v3x - v0x;
- t2y = v3y - v0y;
- t2z = v3z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- if ((v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z < 0) {
- v1x = v3x;
- v1y = v3y;
- v1z = v3z;
- v11x = v31x;
- v11y = v31y;
- v11z = v31z;
- v12x = v32x;
- v12y = v32y;
- v12z = v32z;
- t1x = v3x - v0x;
- t1y = v3y - v0y;
- t1z = v3z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- var hit = false;
- while (true) {
- t1x = v2x - v1x;
- t1y = v2y - v1y;
- t1z = v2z - v1z;
- t2x = v3x - v1x;
- t2y = v3y - v1y;
- t2z = v3z - v1z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- len = 1 / OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- nx *= len;
- ny *= len;
- nz *= len;
- if (nx * v1x + ny * v1y + nz * v1z >= 0 && !hit) {
- var b0 = (v1y * v2z - v1z * v2y) * v3x + (v1z * v2x - v1x * v2z) * v3y + (v1x * v2y - v1y * v2x) * v3z;
- var b1 = (v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z;
- var b2 = (v0y * v1z - v0z * v1y) * v3x + (v0z * v1x - v0x * v1z) * v3y + (v0x * v1y - v0y * v1x) * v3z;
- var b3 = (v2y * v1z - v2z * v1y) * v0x + (v2z * v1x - v2x * v1z) * v0y + (v2x * v1y - v2y * v1x) * v0z;
- var sum = b0 + b1 + b2 + b3;
- if (sum <= 0) {
- b0 = 0;
- b1 = (v2y * v3z - v2z * v3y) * nx + (v2z * v3x - v2x * v3z) * ny + (v2x * v3y - v2y * v3x) * nz;
- b2 = (v3y * v2z - v3z * v2y) * nx + (v3z * v2x - v3x * v2z) * ny + (v3x * v2y - v3y * v2x) * nz;
- b3 = (v1y * v2z - v1z * v2y) * nx + (v1z * v2x - v1x * v2z) * ny + (v1x * v2y - v1y * v2x) * nz;
- sum = b1 + b2 + b3;
- }
- var inv = 1 / sum;
- p1x = (v01x * b0 + v11x * b1 + v21x * b2 + v31x * b3) * inv;
- p1y = (v01y * b0 + v11y * b1 + v21y * b2 + v31y * b3) * inv;
- p1z = (v01z * b0 + v11z * b1 + v21z * b2 + v31z * b3) * inv;
- p2x = (v02x * b0 + v12x * b1 + v22x * b2 + v32x * b3) * inv;
- p2y = (v02y * b0 + v12y * b1 + v22y * b2 + v32y * b3) * inv;
- p2z = (v02z * b0 + v12z * b1 + v22z * b2 + v32z * b3) * inv;
- hit = true;
- }
- this.supportPointB(c1, -nx, -ny, -nz, sup);
- var v41x = sup.x;
- var v41y = sup.y;
- var v41z = sup.z;
- this.supportPointC(c2, nx, ny, nz, sup);
- var v42x = sup.x;
- var v42y = sup.y;
- var v42z = sup.z;
- var v4x = v42x - v41x;
- var v4y = v42y - v41y;
- var v4z = v42z - v41z;
- var separation = -(v4x * nx + v4y * ny + v4z * nz);
- if ((v4x - v3x) * nx + (v4y - v3y) * ny + (v4z - v3z) * nz <= 0.01 || separation >= 0) {
- if (hit) {
- sep.init(-nx, -ny, -nz);
- pos.init((p1x + p2x) * 0.5, (p1y + p2y) * 0.5, (p1z + p2z) * 0.5);
- dep.x = separation;
- return true;
- }
- return false;
- }
- if (
- (v4y * v1z - v4z * v1y) * v0x +
- (v4z * v1x - v4x * v1z) * v0y +
- (v4x * v1y - v4y * v1x) * v0z < 0
- ) {
- if (
- (v4y * v2z - v4z * v2y) * v0x +
- (v4z * v2x - v4x * v2z) * v0y +
- (v4x * v2y - v4y * v2x) * v0z < 0
- ) {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- } else {
- v3x = v4x;
- v3y = v4y;
- v3z = v4z;
- v31x = v41x;
- v31y = v41y;
- v31z = v41z;
- v32x = v42x;
- v32y = v42y;
- v32z = v42z;
- }
- } else {
- if (
- (v4y * v3z - v4z * v3y) * v0x +
- (v4z * v3x - v4x * v3z) * v0y +
- (v4x * v3y - v4y * v3x) * v0z < 0
- ) {
- v2x = v4x;
- v2y = v4y;
- v2z = v4z;
- v21x = v41x;
- v21y = v41y;
- v21z = v41z;
- v22x = v42x;
- v22y = v42y;
- v22z = v42z;
- } else {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- }
- }
- }
- }
- //return false;
- };
- OIMO.BoxCylinderCollisionDetector.prototype.supportPointB = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var w = c.halfWidth;
- var h = c.halfHeight;
- var d = c.halfDepth;
- var ox;
- var oy;
- var oz;
- if (ldx < 0) ox = -w;
- else ox = w;
- if (ldy < 0) oy = -h;
- else oy = h;
- if (ldz < 0) oz = -d;
- else oz = d;
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.BoxCylinderCollisionDetector.prototype.supportPointC = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var radx = ldx;
- var radz = ldz;
- var len = radx * radx + radz * radz;
- var rad = c.radius;
- var hh = c.halfHeight;
- var ox;
- var oy;
- var oz;
- if (len == 0) {
- if (ldy < 0) {
- ox = rad;
- oy = -hh;
- oz = 0;
- } else {
- ox = rad;
- oy = hh;
- oz = 0;
- }
- } else {
- len = c.radius / OIMO.sqrt(len);
- if (ldy < 0) {
- ox = radx * len;
- oy = -hh;
- oz = radz * len;
- } else {
- ox = radx * len;
- oy = hh;
- oz = radz * len;
- }
- }
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.BoxCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var b;
- var c;
- if (this.flip) {
- b = shape2;
- c = shape1;
- } else {
- b = shape1;
- c = shape2;
- }
- var sep = new OIMO.Vec3();
- var pos = new OIMO.Vec3();
- var dep = new OIMO.Vec3();
- var co;
- if (!this.getSep(b, c, sep, pos, dep)) return;
- var pbx = b.position.x;
- var pby = b.position.y;
- var pbz = b.position.z;
- var pcx = c.position.x;
- var pcy = c.position.y;
- var pcz = c.position.z;
- var bw = b.halfWidth;
- var bh = b.halfHeight;
- var bd = b.halfDepth;
- var ch = c.halfHeight;
- var r = c.radius;
- var D = b.dimentions;
- var nwx = D[0];//b.normalDirectionWidth.x;
- var nwy = D[1];//b.normalDirectionWidth.y;
- var nwz = D[2];//b.normalDirectionWidth.z;
- var nhx = D[3];//b.normalDirectionHeight.x;
- var nhy = D[4];//b.normalDirectionHeight.y;
- var nhz = D[5];//b.normalDirectionHeight.z;
- var ndx = D[6];//b.normalDirectionDepth.x;
- var ndy = D[7];//b.normalDirectionDepth.y;
- var ndz = D[8];//b.normalDirectionDepth.z;
- var dwx = D[9];//b.halfDirectionWidth.x;
- var dwy = D[10];//b.halfDirectionWidth.y;
- var dwz = D[11];//b.halfDirectionWidth.z;
- var dhx = D[12];//b.halfDirectionHeight.x;
- var dhy = D[13];//b.halfDirectionHeight.y;
- var dhz = D[14];//b.halfDirectionHeight.z;
- var ddx = D[15];//b.halfDirectionDepth.x;
- var ddy = D[16];//b.halfDirectionDepth.y;
- var ddz = D[17];//b.halfDirectionDepth.z;
- var ncx = c.normalDirection.x;
- var ncy = c.normalDirection.y;
- var ncz = c.normalDirection.z;
- var dcx = c.halfDirection.x;
- var dcy = c.halfDirection.y;
- var dcz = c.halfDirection.z;
- var nx = sep.x;
- var ny = sep.y;
- var nz = sep.z;
- var dotw = nx * nwx + ny * nwy + nz * nwz;
- var doth = nx * nhx + ny * nhy + nz * nhz;
- var dotd = nx * ndx + ny * ndy + nz * ndz;
- var dotc = nx * ncx + ny * ncy + nz * ncz;
- var right1 = dotw > 0;
- var right2 = doth > 0;
- var right3 = dotd > 0;
- var right4 = dotc > 0;
- if (!right1) dotw = -dotw;
- if (!right2) doth = -doth;
- if (!right3) dotd = -dotd;
- if (!right4) dotc = -dotc;
- var state = 0;
- if (dotc > 0.999) {
- if (dotw > 0.999) {
- if (dotw > dotc) state = 1;
- else state = 4;
- } else if (doth > 0.999) {
- if (doth > dotc) state = 2;
- else state = 4;
- } else if (dotd > 0.999) {
- if (dotd > dotc) state = 3;
- else state = 4;
- } else state = 4;
- } else {
- if (dotw > 0.999) state = 1;
- else if (doth > 0.999) state = 2;
- else if (dotd > 0.999) state = 3;
- }
- var cbx;
- var cby;
- var cbz;
- var ccx;
- var ccy;
- var ccz;
- var r00;
- var r01;
- var r02;
- var r10;
- var r11;
- var r12;
- var r20;
- var r21;
- var r22;
- var px;
- var py;
- var pz;
- var pd;
- var dot;
- var len;
- var tx;
- var ty;
- var tz;
- var td;
- var dx;
- var dy;
- var dz;
- var d1x;
- var d1y;
- var d1z;
- var d2x;
- var d2y;
- var d2z;
- var sx;
- var sy;
- var sz;
- var sd;
- var ex;
- var ey;
- var ez;
- var ed;
- var dot1;
- var dot2;
- var t1;
- var t2;
- var dir1x;
- var dir1y;
- var dir1z;
- var dir2x;
- var dir2y;
- var dir2z;
- var dir1l;
- var dir2l;
- if (state == 0) {
- //manifold.addPoint(pos.x,pos.y,pos.z,nx,ny,nz,dep.x,b,c,0,0,false);
- manifold.addPoint(pos.x, pos.y, pos.z, nx, ny, nz, dep.x, this.flip);
- } else if (state == 4) {
- if (right4) {
- ccx = pcx - dcx;
- ccy = pcy - dcy;
- ccz = pcz - dcz;
- nx = -ncx;
- ny = -ncy;
- nz = -ncz;
- } else {
- ccx = pcx + dcx;
- ccy = pcy + dcy;
- ccz = pcz + dcz;
- nx = ncx;
- ny = ncy;
- nz = ncz;
- }
- var v1x;
- var v1y;
- var v1z;
- var v2x;
- var v2y;
- var v2z;
- var v3x;
- var v3y;
- var v3z;
- var v4x;
- var v4y;
- var v4z;
- dot = 1;
- state = 0;
- dot1 = nwx * nx + nwy * ny + nwz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 0;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 1;
- }
- dot1 = nhx * nx + nhy * ny + nhz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 2;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 3;
- }
- dot1 = ndx * nx + ndy * ny + ndz * nz;
- if (dot1 < dot) {
- dot = dot1;
- state = 4;
- }
- if (-dot1 < dot) {
- dot = -dot1;
- state = 5;
- }
- var v = b.elements;
- switch (state) {
- case 0:
- //v=b.vertex1;
- v1x = v[0];//v.x;
- v1y = v[1];//v.y;
- v1z = v[2];//v.z;
- //v=b.vertex3;
- v2x = v[6];//v.x;
- v2y = v[7];//v.y;
- v2z = v[8];//v.z;
- //v=b.vertex4;
- v3x = v[9];//v.x;
- v3y = v[10];//v.y;
- v3z = v[11];//v.z;
- //v=b.vertex2;
- v4x = v[3];//v.x;
- v4y = v[4];//v.y;
- v4z = v[5];//v.z;
- break;
- case 1:
- //v=b.vertex6;
- v1x = v[15];//v.x;
- v1y = v[16];//v.y;
- v1z = v[17];//v.z;
- //v=b.vertex8;
- v2x = v[21];//v.x;
- v2y = v[22];//v.y;
- v2z = v[23];//v.z;
- //v=b.vertex7;
- v3x = v[18];//v.x;
- v3y = v[19];//v.y;
- v3z = v[20];//v.z;
- //v=b.vertex5;
- v4x = v[12];//v.x;
- v4y = v[13];//v.y;
- v4z = v[14];//v.z;
- break;
- case 2:
- //v=b.vertex5;
- v1x = v[12];//v.x;
- v1y = v[13];//v.y;
- v1z = v[14];//v.z;
- //v=b.vertex1;
- v2x = v[0];//v.x;
- v2y = v[1];//v.y;
- v2z = v[2];//v.z;
- //v=b.vertex2;
- v3x = v[3];//v.x;
- v3y = v[4];//v.y;
- v3z = v[5];//v.z;
- //v=b.vertex6;
- v4x = v[15];//v.x;
- v4y = v[16];//v.y;
- v4z = v[17];//v.z;
- break;
- case 3:
- //v=b.vertex8;
- v1x = v[21];//v.x;
- v1y = v[22];//v.y;
- v1z = v[23];//v.z;
- //v=b.vertex4;
- v2x = v[9];//v.x;
- v2y = v[10];//v.y;
- v2z = v[11];//v.z;
- //v=b.vertex3;
- v3x = v[6];//v.x;
- v3y = v[7];//v.y;
- v3z = v[8];//v.z;
- //v=b.vertex7;
- v4x = v[18];//v.x;
- v4y = v[19];//v.y;
- v4z = v[20];//v.z;
- break;
- case 4:
- //v=b.vertex5;
- v1x = v[12];//v.x;
- v1y = v[13];//v.y;
- v1z = v[14];//v.z;
- //v=b.vertex7;
- v2x = v[18];//v.x;
- v2y = v[19];//v.y;
- v2z = v[20];//v.z;
- //v=b.vertex3;
- v3x = v[6];//v.x;
- v3y = v[7];//v.y;
- v3z = v[8];//v.z;
- //v=b.vertex1;
- v4x = v[0];//v.x;
- v4y = v[1];//v.y;
- v4z = v[2];//v.z;
- break;
- case 5:
- //v=b.vertex2;
- v1x = v[3];//v.x;
- v1y = v[4];//v.y;
- v1z = v[5];//v.z;
- //v=b.vertex4;
- v2x = v[9];//v.x;
- v2y = v[10];//v.y;
- v2z = v[11];//v.z;
- //v=b.vertex8;
- v3x = v[21];//v.x;
- v3y = v[22];//v.y;
- v3z = v[23];//v.z;
- //v=b.vertex6;
- v4x = v[15];//v.x;
- v4y = v[16];//v.y;
- v4z = v[17];//v.z;
- break;
- }
- pd = nx * (v1x - ccx) + ny * (v1y - ccy) + nz * (v1z - ccz);
- if (pd <= 0) manifold.addPoint(v1x, v1y, v1z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v2x - ccx) + ny * (v2y - ccy) + nz * (v2z - ccz);
- if (pd <= 0) manifold.addPoint(v2x, v2y, v2z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v3x - ccx) + ny * (v3y - ccy) + nz * (v3z - ccz);
- if (pd <= 0) manifold.addPoint(v3x, v3y, v3z, -nx, -ny, -nz, pd, this.flip);
- pd = nx * (v4x - ccx) + ny * (v4y - ccy) + nz * (v4z - ccz);
- if (pd <= 0) manifold.addPoint(v4x, v4y, v4z, -nx, -ny, -nz, pd, this.flip);
- } else {
- switch (state) {
- case 1:
- if (right1) {
- cbx = pbx + dwx;
- cby = pby + dwy;
- cbz = pbz + dwz;
- nx = nwx;
- ny = nwy;
- nz = nwz;
- } else {
- cbx = pbx - dwx;
- cby = pby - dwy;
- cbz = pbz - dwz;
- nx = -nwx;
- ny = -nwy;
- nz = -nwz;
- }
- dir1x = nhx;
- dir1y = nhy;
- dir1z = nhz;
- dir1l = bh;
- dir2x = ndx;
- dir2y = ndy;
- dir2z = ndz;
- dir2l = bd;
- break;
- case 2:
- if (right2) {
- cbx = pbx + dhx;
- cby = pby + dhy;
- cbz = pbz + dhz;
- nx = nhx;
- ny = nhy;
- nz = nhz;
- } else {
- cbx = pbx - dhx;
- cby = pby - dhy;
- cbz = pbz - dhz;
- nx = -nhx;
- ny = -nhy;
- nz = -nhz;
- }
- dir1x = nwx;
- dir1y = nwy;
- dir1z = nwz;
- dir1l = bw;
- dir2x = ndx;
- dir2y = ndy;
- dir2z = ndz;
- dir2l = bd;
- break;
- case 3:
- if (right3) {
- cbx = pbx + ddx;
- cby = pby + ddy;
- cbz = pbz + ddz;
- nx = ndx;
- ny = ndy;
- nz = ndz;
- } else {
- cbx = pbx - ddx;
- cby = pby - ddy;
- cbz = pbz - ddz;
- nx = -ndx;
- ny = -ndy;
- nz = -ndz;
- }
- dir1x = nwx;
- dir1y = nwy;
- dir1z = nwz;
- dir1l = bw;
- dir2x = nhx;
- dir2y = nhy;
- dir2z = nhz;
- dir2l = bh;
- break;
- }
- dot = nx * ncx + ny * ncy + nz * ncz;
- if (dot < 0) len = ch;
- else len = -ch;
- ccx = pcx + len * ncx;
- ccy = pcy + len * ncy;
- ccz = pcz + len * ncz;
- if (dotc >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * ncx + ty * ncy + tz * ncz;
- dx = len * ncx - tx;
- dy = len * ncy - ty;
- dz = len * ncz - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) return;
- len = r / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = ccx + dx;
- ty = ccy + dy;
- tz = ccz + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = ncx * ncx * 1.5 - 0.5;
- r01 = ncx * ncy * 1.5 - ncz * 0.866025403;
- r02 = ncx * ncz * 1.5 + ncy * 0.866025403;
- r10 = ncy * ncx * 1.5 + ncz * 0.866025403;
- r11 = ncy * ncy * 1.5 - 0.5;
- r12 = ncy * ncz * 1.5 - ncx * 0.866025403;
- r20 = ncz * ncx * 1.5 - ncy * 0.866025403;
- r21 = ncz * ncy * 1.5 + ncx * 0.866025403;
- r22 = ncz * ncz * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + ccx;
- py = (dy = py) + ccy;
- pz = (dz = pz) + ccz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- if (pd <= 0) {
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- //manifold.addPoint(px,py,pz,nx,ny,nz,pd,b,c,2,0,false);
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + ccx;
- py = (dy = py) + ccy;
- pz = (dz = pz) + ccz;
- pd = nx * (px - cbx) + ny * (py - cby) + nz * (pz - cbz);
- if (pd <= 0) {
- tx = px - pd * nx - cbx;
- ty = py - pd * ny - cby;
- tz = pz - pd * nz - cbz;
- sd = dir1x * tx + dir1y * ty + dir1z * tz;
- ed = dir2x * tx + dir2y * ty + dir2z * tz;
- if (sd < -dir1l) sd = -dir1l;
- else if (sd > dir1l) sd = dir1l;
- if (ed < -dir2l) ed = -dir2l;
- else if (ed > dir2l) ed = dir2l;
- tx = sd * dir1x + ed * dir2x;
- ty = sd * dir1y + ed * dir2y;
- tz = sd * dir1z + ed * dir2z;
- px = cbx + tx;
- py = cby + ty;
- pz = cbz + tz;
- //manifold.addPoint(px,py,pz,nx,ny,nz,pd,b,c,3,0,false);
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, this.flip);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- sd = nx * (sx - cbx) + ny * (sy - cby) + nz * (sz - cbz);
- sx -= sd * nx;
- sy -= sd * ny;
- sz -= sd * nz;
- if (dot > 0) {
- ex = tx + dcx * 2;
- ey = ty + dcy * 2;
- ez = tz + dcz * 2;
- } else {
- ex = tx - dcx * 2;
- ey = ty - dcy * 2;
- ez = tz - dcz * 2;
- }
- ed = nx * (ex - cbx) + ny * (ey - cby) + nz * (ez - cbz);
- ex -= ed * nx;
- ey -= ed * ny;
- ez -= ed * nz;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- dotw = d1x * dir1x + d1y * dir1y + d1z * dir1z;
- doth = d2x * dir1x + d2y * dir1y + d2z * dir1z;
- dot1 = dotw - dir1l;
- dot2 = doth - dir1l;
- if (dot1 > 0) {
- if (dot2 > 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- dotw = d1x * dir1x + d1y * dir1y + d1z * dir1z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 > 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- doth = d2x * dir1x + d2y * dir1y + d2z * dir1z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dot1 = dotw + dir1l;
- dot2 = doth + dir1l;
- if (dot1 < 0) {
- if (dot2 < 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 < 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dotw = d1x * dir2x + d1y * dir2y + d1z * dir2z;
- doth = d2x * dir2x + d2y * dir2y + d2z * dir2z;
- dot1 = dotw - dir2l;
- dot2 = doth - dir2l;
- if (dot1 > 0) {
- if (dot2 > 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- d1x = sx - cbx;
- d1y = sy - cby;
- d1z = sz - cbz;
- dotw = d1x * dir2x + d1y * dir2y + d1z * dir2z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- } else if (dot2 > 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- d2x = ex - cbx;
- d2y = ey - cby;
- d2z = ez - cbz;
- doth = d2x * dir2x + d2y * dir2y + d2z * dir2z;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- td = ed - sd;
- }
- dot1 = dotw + dir2l;
- dot2 = doth + dir2l;
- if (dot1 < 0) {
- if (dot2 < 0) return;
- t1 = dot1 / (dot1 - dot2);
- sx = sx + tx * t1;
- sy = sy + ty * t1;
- sz = sz + tz * t1;
- sd = sd + td * t1;
- } else if (dot2 < 0) {
- t1 = dot1 / (dot1 - dot2);
- ex = sx + tx * t1;
- ey = sy + ty * t1;
- ez = sz + tz * t1;
- ed = sd + td * t1;
- }
- if (sd < 0) {
- //manifold.addPoint(sx,sy,sz,nx,ny,nz,sd,b,c,1,0,false);
- manifold.addPoint(sx, sy, sz, nx, ny, nz, sd, this.flip);
- }
- if (ed < 0) {
- //manifold.addPoint(ex,ey,ez,nx,ny,nz,ed,b,c,4,0,false);
- manifold.addPoint(ex, ey, ez, nx, ny, nz, ed, this.flip);
- }
- }
- }
- };
- OIMO.CylinderCylinderCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.CylinderCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.CylinderCylinderCollisionDetector.prototype.constructor = OIMO.CylinderCylinderCollisionDetector;
- OIMO.CylinderCylinderCollisionDetector.prototype.getSep = function (c1, c2, sep, pos, dep) {
- var t1x;
- var t1y;
- var t1z;
- var t2x;
- var t2y;
- var t2z;
- var sup = new OIMO.Vec3();
- var len;
- var p1x;
- var p1y;
- var p1z;
- var p2x;
- var p2y;
- var p2z;
- var v01x = c1.position.x;
- var v01y = c1.position.y;
- var v01z = c1.position.z;
- var v02x = c2.position.x;
- var v02y = c2.position.y;
- var v02z = c2.position.z;
- var v0x = v02x - v01x;
- var v0y = v02y - v01y;
- var v0z = v02z - v01z;
- if (v0x * v0x + v0y * v0y + v0z * v0z == 0) v0y = 0.001;
- var nx = -v0x;
- var ny = -v0y;
- var nz = -v0z;
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v11x = sup.x;
- var v11y = sup.y;
- var v11z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v12x = sup.x;
- var v12y = sup.y;
- var v12z = sup.z;
- var v1x = v12x - v11x;
- var v1y = v12y - v11y;
- var v1z = v12z - v11z;
- if (v1x * nx + v1y * ny + v1z * nz <= 0) {
- return false;
- }
- nx = v1y * v0z - v1z * v0y;
- ny = v1z * v0x - v1x * v0z;
- nz = v1x * v0y - v1y * v0x;
- if (nx * nx + ny * ny + nz * nz == 0) {
- sep.init(v1x - v0x, v1y - v0y, v1z - v0z);
- sep.normalize(sep);
- pos.init((v11x + v12x) * 0.5, (v11y + v12y) * 0.5, (v11z + v12z) * 0.5);
- return true;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v21x = sup.x;
- var v21y = sup.y;
- var v21z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v22x = sup.x;
- var v22y = sup.y;
- var v22z = sup.z;
- var v2x = v22x - v21x;
- var v2y = v22y - v21y;
- var v2z = v22z - v21z;
- if (v2x * nx + v2y * ny + v2z * nz <= 0) {
- return false;
- }
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- if (nx * v0x + ny * v0y + nz * v0z > 0) {
- t1x = v1x;
- t1y = v1y;
- t1z = v1z;
- v1x = v2x;
- v1y = v2y;
- v1z = v2z;
- v2x = t1x;
- v2y = t1y;
- v2z = t1z;
- t1x = v11x;
- t1y = v11y;
- t1z = v11z;
- v11x = v21x;
- v11y = v21y;
- v11z = v21z;
- v21x = t1x;
- v21y = t1y;
- v21z = t1z;
- t1x = v12x;
- t1y = v12y;
- t1z = v12z;
- v12x = v22x;
- v12y = v22y;
- v12z = v22z;
- v22x = t1x;
- v22y = t1y;
- v22z = t1z;
- nx = -nx;
- ny = -ny;
- nz = -nz;
- }
- var iterations = 0;
- while (true) {
- if (++iterations > 100) {
- return false;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v31x = sup.x;
- var v31y = sup.y;
- var v31z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v32x = sup.x;
- var v32y = sup.y;
- var v32z = sup.z;
- var v3x = v32x - v31x;
- var v3y = v32y - v31y;
- var v3z = v32z - v31z;
- if (v3x * nx + v3y * ny + v3z * nz <= 0) {
- return false;
- }
- if ((v1y * v3z - v1z * v3y) * v0x + (v1z * v3x - v1x * v3z) * v0y + (v1x * v3y - v1y * v3x) * v0z < 0) {
- v2x = v3x;
- v2y = v3y;
- v2z = v3z;
- v21x = v31x;
- v21y = v31y;
- v21z = v31z;
- v22x = v32x;
- v22y = v32y;
- v22z = v32z;
- t1x = v1x - v0x;
- t1y = v1y - v0y;
- t1z = v1z - v0z;
- t2x = v3x - v0x;
- t2y = v3y - v0y;
- t2z = v3z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- if ((v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z < 0) {
- v1x = v3x;
- v1y = v3y;
- v1z = v3z;
- v11x = v31x;
- v11y = v31y;
- v11z = v31z;
- v12x = v32x;
- v12y = v32y;
- v12z = v32z;
- t1x = v3x - v0x;
- t1y = v3y - v0y;
- t1z = v3z - v0z;
- t2x = v2x - v0x;
- t2y = v2y - v0y;
- t2z = v2z - v0z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- continue;
- }
- var hit = false;
- while (true) {
- t1x = v2x - v1x;
- t1y = v2y - v1y;
- t1z = v2z - v1z;
- t2x = v3x - v1x;
- t2y = v3y - v1y;
- t2z = v3z - v1z;
- nx = t1y * t2z - t1z * t2y;
- ny = t1z * t2x - t1x * t2z;
- nz = t1x * t2y - t1y * t2x;
- len = 1 / OIMO.sqrt(nx * nx + ny * ny + nz * nz);
- nx *= len;
- ny *= len;
- nz *= len;
- if (nx * v1x + ny * v1y + nz * v1z >= 0 && !hit) {
- var b0 = (v1y * v2z - v1z * v2y) * v3x + (v1z * v2x - v1x * v2z) * v3y + (v1x * v2y - v1y * v2x) * v3z;
- var b1 = (v3y * v2z - v3z * v2y) * v0x + (v3z * v2x - v3x * v2z) * v0y + (v3x * v2y - v3y * v2x) * v0z;
- var b2 = (v0y * v1z - v0z * v1y) * v3x + (v0z * v1x - v0x * v1z) * v3y + (v0x * v1y - v0y * v1x) * v3z;
- var b3 = (v2y * v1z - v2z * v1y) * v0x + (v2z * v1x - v2x * v1z) * v0y + (v2x * v1y - v2y * v1x) * v0z;
- var sum = b0 + b1 + b2 + b3;
- if (sum <= 0) {
- b0 = 0;
- b1 = (v2y * v3z - v2z * v3y) * nx + (v2z * v3x - v2x * v3z) * ny + (v2x * v3y - v2y * v3x) * nz;
- b2 = (v3y * v2z - v3z * v2y) * nx + (v3z * v2x - v3x * v2z) * ny + (v3x * v2y - v3y * v2x) * nz;
- b3 = (v1y * v2z - v1z * v2y) * nx + (v1z * v2x - v1x * v2z) * ny + (v1x * v2y - v1y * v2x) * nz;
- sum = b1 + b2 + b3;
- }
- var inv = 1 / sum;
- p1x = (v01x * b0 + v11x * b1 + v21x * b2 + v31x * b3) * inv;
- p1y = (v01y * b0 + v11y * b1 + v21y * b2 + v31y * b3) * inv;
- p1z = (v01z * b0 + v11z * b1 + v21z * b2 + v31z * b3) * inv;
- p2x = (v02x * b0 + v12x * b1 + v22x * b2 + v32x * b3) * inv;
- p2y = (v02y * b0 + v12y * b1 + v22y * b2 + v32y * b3) * inv;
- p2z = (v02z * b0 + v12z * b1 + v22z * b2 + v32z * b3) * inv;
- hit = true;
- }
- this.supportPoint(c1, -nx, -ny, -nz, sup);
- var v41x = sup.x;
- var v41y = sup.y;
- var v41z = sup.z;
- this.supportPoint(c2, nx, ny, nz, sup);
- var v42x = sup.x;
- var v42y = sup.y;
- var v42z = sup.z;
- var v4x = v42x - v41x;
- var v4y = v42y - v41y;
- var v4z = v42z - v41z;
- var separation = -(v4x * nx + v4y * ny + v4z * nz);
- if ((v4x - v3x) * nx + (v4y - v3y) * ny + (v4z - v3z) * nz <= 0.01 || separation >= 0) {
- if (hit) {
- sep.init(-nx, -ny, -nz);
- pos.init((p1x + p2x) * 0.5, (p1y + p2y) * 0.5, (p1z + p2z) * 0.5);
- dep.x = separation;
- return true;
- }
- return false;
- }
- if (
- (v4y * v1z - v4z * v1y) * v0x +
- (v4z * v1x - v4x * v1z) * v0y +
- (v4x * v1y - v4y * v1x) * v0z < 0
- ) {
- if (
- (v4y * v2z - v4z * v2y) * v0x +
- (v4z * v2x - v4x * v2z) * v0y +
- (v4x * v2y - v4y * v2x) * v0z < 0
- ) {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- } else {
- v3x = v4x;
- v3y = v4y;
- v3z = v4z;
- v31x = v41x;
- v31y = v41y;
- v31z = v41z;
- v32x = v42x;
- v32y = v42y;
- v32z = v42z;
- }
- } else {
- if (
- (v4y * v3z - v4z * v3y) * v0x +
- (v4z * v3x - v4x * v3z) * v0y +
- (v4x * v3y - v4y * v3x) * v0z < 0
- ) {
- v2x = v4x;
- v2y = v4y;
- v2z = v4z;
- v21x = v41x;
- v21y = v41y;
- v21z = v41z;
- v22x = v42x;
- v22y = v42y;
- v22z = v42z;
- } else {
- v1x = v4x;
- v1y = v4y;
- v1z = v4z;
- v11x = v41x;
- v11y = v41y;
- v11z = v41z;
- v12x = v42x;
- v12y = v42y;
- v12z = v42z;
- }
- }
- }
- }
- //return false;
- };
- OIMO.CylinderCylinderCollisionDetector.prototype.supportPoint = function (c, dx, dy, dz, out) {
- var rot = c.rotation.elements;
- var ldx = rot[0] * dx + rot[3] * dy + rot[6] * dz;
- var ldy = rot[1] * dx + rot[4] * dy + rot[7] * dz;
- var ldz = rot[2] * dx + rot[5] * dy + rot[8] * dz;
- var radx = ldx;
- var radz = ldz;
- var len = radx * radx + radz * radz;
- var rad = c.radius;
- var hh = c.halfHeight;
- var ox;
- var oy;
- var oz;
- if (len == 0) {
- if (ldy < 0) {
- ox = rad;
- oy = -hh;
- oz = 0;
- } else {
- ox = rad;
- oy = hh;
- oz = 0;
- }
- } else {
- len = c.radius / OIMO.sqrt(len);
- if (ldy < 0) {
- ox = radx * len;
- oy = -hh;
- oz = radz * len;
- } else {
- ox = radx * len;
- oy = hh;
- oz = radz * len;
- }
- }
- ldx = rot[0] * ox + rot[1] * oy + rot[2] * oz + c.position.x;
- ldy = rot[3] * ox + rot[4] * oy + rot[5] * oz + c.position.y;
- ldz = rot[6] * ox + rot[7] * oy + rot[8] * oz + c.position.z;
- out.init(ldx, ldy, ldz);
- };
- OIMO.CylinderCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var c1;
- var c2;
- if (shape1.id < shape2.id) {
- c1 = shape1;
- c2 = shape2;
- } else {
- c1 = shape2;
- c2 = shape1;
- }
- var p1 = c1.position;
- var p2 = c2.position;
- var p1x = p1.x;
- var p1y = p1.y;
- var p1z = p1.z;
- var p2x = p2.x;
- var p2y = p2.y;
- var p2z = p2.z;
- var h1 = c1.halfHeight;
- var h2 = c2.halfHeight;
- var n1 = c1.normalDirection;
- var n2 = c2.normalDirection;
- var d1 = c1.halfDirection;
- var d2 = c2.halfDirection;
- var r1 = c1.radius;
- var r2 = c2.radius;
- var n1x = n1.x;
- var n1y = n1.y;
- var n1z = n1.z;
- var n2x = n2.x;
- var n2y = n2.y;
- var n2z = n2.z;
- var d1x = d1.x;
- var d1y = d1.y;
- var d1z = d1.z;
- var d2x = d2.x;
- var d2y = d2.y;
- var d2z = d2.z;
- var dx = p1x - p2x;
- var dy = p1y - p2y;
- var dz = p1z - p2z;
- var len;
- var len1;
- var len2;
- var c;
- var c1x;
- var c1y;
- var c1z;
- var c2x;
- var c2y;
- var c2z;
- var tx;
- var ty;
- var tz;
- var sx;
- var sy;
- var sz;
- var ex;
- var ey;
- var ez;
- var depth1;
- var depth2;
- var dot;
- var t1;
- var t2;
- var sep = new OIMO.Vec3();
- var pos = new OIMO.Vec3();
- var dep = new OIMO.Vec3();
- if (!this.getSep(c1, c2, sep, pos, dep)) return;
- var dot1 = sep.x * n1x + sep.y * n1y + sep.z * n1z;
- var dot2 = sep.x * n2x + sep.y * n2y + sep.z * n2z;
- var right1 = dot1 > 0;
- var right2 = dot2 > 0;
- if (!right1) dot1 = -dot1;
- if (!right2) dot2 = -dot2;
- var state = 0;
- if (dot1 > 0.999 || dot2 > 0.999) {
- if (dot1 > dot2) state = 1;
- else state = 2;
- }
- var nx;
- var ny;
- var nz;
- var depth = dep.x;
- var r00;
- var r01;
- var r02;
- var r10;
- var r11;
- var r12;
- var r20;
- var r21;
- var r22;
- var px;
- var py;
- var pz;
- var pd;
- var a;
- var b;
- var e;
- var f;
- nx = sep.x;
- ny = sep.y;
- nz = sep.z;
- switch (state) {
- case 0:
- manifold.addPoint(pos.x, pos.y, pos.z, nx, ny, nz, depth, false);
- break;
- case 1:
- if (right1) {
- c1x = p1x + d1x;
- c1y = p1y + d1y;
- c1z = p1z + d1z;
- nx = n1x;
- ny = n1y;
- nz = n1z;
- } else {
- c1x = p1x - d1x;
- c1y = p1y - d1y;
- c1z = p1z - d1z;
- nx = -n1x;
- ny = -n1y;
- nz = -n1z;
- }
- dot = nx * n2x + ny * n2y + nz * n2z;
- if (dot < 0) len = h2;
- else len = -h2;
- c2x = p2x + len * n2x;
- c2y = p2y + len * n2y;
- c2z = p2z + len * n2z;
- if (dot2 >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * n2x + ty * n2y + tz * n2z;
- dx = len * n2x - tx;
- dy = len * n2y - ty;
- dz = len * n2z - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) break;
- len = r2 / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = c2x + dx;
- ty = c2y + dy;
- tz = c2z + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = n2x * n2x * 1.5 - 0.5;
- r01 = n2x * n2y * 1.5 - n2z * 0.866025403;
- r02 = n2x * n2z * 1.5 + n2y * 0.866025403;
- r10 = n2y * n2x * 1.5 + n2z * 0.866025403;
- r11 = n2y * n2y * 1.5 - 0.5;
- r12 = n2y * n2z * 1.5 - n2x * 0.866025403;
- r20 = n2z * n2x * 1.5 - n2y * 0.866025403;
- r21 = n2z * n2y * 1.5 + n2x * 0.866025403;
- r22 = n2z * n2z * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c2x;
- py = (dy = py) + c2y;
- pz = (dz = pz) + c2z;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- if (pd <= 0) {
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c2x;
- py = (dy = py) + c2y;
- pz = (dz = pz) + c2z;
- pd = nx * (px - c1x) + ny * (py - c1y) + nz * (pz - c1z);
- if (pd <= 0) {
- tx = px - pd * nx - c1x;
- ty = py - pd * ny - c1y;
- tz = pz - pd * nz - c1z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r1 * r1) {
- len = r1 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c1x + tx;
- py = c1y + ty;
- pz = c1z + tz;
- manifold.addPoint(px, py, pz, nx, ny, nz, pd, false);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- depth1 = nx * (sx - c1x) + ny * (sy - c1y) + nz * (sz - c1z);
- sx -= depth1 * nx;
- sy -= depth1 * ny;
- sz -= depth1 * nz;
- if (dot > 0) {
- ex = tx + n2x * h2 * 2;
- ey = ty + n2y * h2 * 2;
- ez = tz + n2z * h2 * 2;
- } else {
- ex = tx - n2x * h2 * 2;
- ey = ty - n2y * h2 * 2;
- ez = tz - n2z * h2 * 2;
- }
- depth2 = nx * (ex - c1x) + ny * (ey - c1y) + nz * (ez - c1z);
- ex -= depth2 * nx;
- ey -= depth2 * ny;
- ez -= depth2 * nz;
- dx = c1x - sx;
- dy = c1y - sy;
- dz = c1z - sz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- a = dx * dx + dy * dy + dz * dz;
- b = dx * tx + dy * ty + dz * tz;
- e = tx * tx + ty * ty + tz * tz;
- f = b * b - e * (a - r1 * r1);
- if (f < 0) break;
- f = OIMO.sqrt(f);
- t1 = (b + f) / e;
- t2 = (b - f) / e;
- if (t2 < t1) {
- len = t1;
- t1 = t2;
- t2 = len;
- }
- if (t2 > 1) t2 = 1;
- if (t1 < 0) t1 = 0;
- tx = sx + (ex - sx) * t1;
- ty = sy + (ey - sy) * t1;
- tz = sz + (ez - sz) * t1;
- ex = sx + (ex - sx) * t2;
- ey = sy + (ey - sy) * t2;
- ez = sz + (ez - sz) * t2;
- sx = tx;
- sy = ty;
- sz = tz;
- len = depth1 + (depth2 - depth1) * t1;
- depth2 = depth1 + (depth2 - depth1) * t2;
- depth1 = len;
- if (depth1 < 0) manifold.addPoint(sx, sy, sz, nx, ny, nz, pd, false);
- if (depth2 < 0) manifold.addPoint(ex, ey, ez, nx, ny, nz, pd, false);
- }
- break;
- case 2:
- if (right2) {
- c2x = p2x - d2x;
- c2y = p2y - d2y;
- c2z = p2z - d2z;
- nx = -n2x;
- ny = -n2y;
- nz = -n2z;
- } else {
- c2x = p2x + d2x;
- c2y = p2y + d2y;
- c2z = p2z + d2z;
- nx = n2x;
- ny = n2y;
- nz = n2z;
- }
- dot = nx * n1x + ny * n1y + nz * n1z;
- if (dot < 0) len = h1;
- else len = -h1;
- c1x = p1x + len * n1x;
- c1y = p1y + len * n1y;
- c1z = p1z + len * n1z;
- if (dot1 >= 0.999999) {
- tx = -ny;
- ty = nz;
- tz = nx;
- } else {
- tx = nx;
- ty = ny;
- tz = nz;
- }
- len = tx * n1x + ty * n1y + tz * n1z;
- dx = len * n1x - tx;
- dy = len * n1y - ty;
- dz = len * n1z - tz;
- len = OIMO.sqrt(dx * dx + dy * dy + dz * dz);
- if (len == 0) break;
- len = r1 / len;
- dx *= len;
- dy *= len;
- dz *= len;
- tx = c1x + dx;
- ty = c1y + dy;
- tz = c1z + dz;
- if (dot < -0.96 || dot > 0.96) {
- r00 = n1x * n1x * 1.5 - 0.5;
- r01 = n1x * n1y * 1.5 - n1z * 0.866025403;
- r02 = n1x * n1z * 1.5 + n1y * 0.866025403;
- r10 = n1y * n1x * 1.5 + n1z * 0.866025403;
- r11 = n1y * n1y * 1.5 - 0.5;
- r12 = n1y * n1z * 1.5 - n1x * 0.866025403;
- r20 = n1z * n1x * 1.5 - n1y * 0.866025403;
- r21 = n1z * n1y * 1.5 + n1x * 0.866025403;
- r22 = n1z * n1z * 1.5 - 0.5;
- px = tx;
- py = ty;
- pz = tz;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c1x;
- py = (dy = py) + c1y;
- pz = (dz = pz) + c1z;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- if (pd <= 0) {
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- }
- px = dx * r00 + dy * r01 + dz * r02;
- py = dx * r10 + dy * r11 + dz * r12;
- pz = dx * r20 + dy * r21 + dz * r22;
- px = (dx = px) + c1x;
- py = (dy = py) + c1y;
- pz = (dz = pz) + c1z;
- pd = nx * (px - c2x) + ny * (py - c2y) + nz * (pz - c2z);
- if (pd <= 0) {
- tx = px - pd * nx - c2x;
- ty = py - pd * ny - c2y;
- tz = pz - pd * nz - c2z;
- len = tx * tx + ty * ty + tz * tz;
- if (len > r2 * r2) {
- len = r2 / OIMO.sqrt(len);
- tx *= len;
- ty *= len;
- tz *= len;
- }
- px = c2x + tx;
- py = c2y + ty;
- pz = c2z + tz;
- manifold.addPoint(px, py, pz, -nx, -ny, -nz, pd, false);
- }
- } else {
- sx = tx;
- sy = ty;
- sz = tz;
- depth1 = nx * (sx - c2x) + ny * (sy - c2y) + nz * (sz - c2z);
- sx -= depth1 * nx;
- sy -= depth1 * ny;
- sz -= depth1 * nz;
- if (dot > 0) {
- ex = tx + n1x * h1 * 2;
- ey = ty + n1y * h1 * 2;
- ez = tz + n1z * h1 * 2;
- } else {
- ex = tx - n1x * h1 * 2;
- ey = ty - n1y * h1 * 2;
- ez = tz - n1z * h1 * 2;
- }
- depth2 = nx * (ex - c2x) + ny * (ey - c2y) + nz * (ez - c2z);
- ex -= depth2 * nx;
- ey -= depth2 * ny;
- ez -= depth2 * nz;
- dx = c2x - sx;
- dy = c2y - sy;
- dz = c2z - sz;
- tx = ex - sx;
- ty = ey - sy;
- tz = ez - sz;
- a = dx * dx + dy * dy + dz * dz;
- b = dx * tx + dy * ty + dz * tz;
- e = tx * tx + ty * ty + tz * tz;
- f = b * b - e * (a - r2 * r2);
- if (f < 0) break;
- f = OIMO.sqrt(f);
- t1 = (b + f) / e;
- t2 = (b - f) / e;
- if (t2 < t1) {
- len = t1;
- t1 = t2;
- t2 = len;
- }
- if (t2 > 1) t2 = 1;
- if (t1 < 0) t1 = 0;
- tx = sx + (ex - sx) * t1;
- ty = sy + (ey - sy) * t1;
- tz = sz + (ez - sz) * t1;
- ex = sx + (ex - sx) * t2;
- ey = sy + (ey - sy) * t2;
- ez = sz + (ez - sz) * t2;
- sx = tx;
- sy = ty;
- sz = tz;
- len = depth1 + (depth2 - depth1) * t1;
- depth2 = depth1 + (depth2 - depth1) * t2;
- depth1 = len;
- if (depth1 < 0) {
- manifold.addPoint(sx, sy, sz, -nx, -ny, -nz, depth1, false);
- }
- if (depth2 < 0) {
- manifold.addPoint(ex, ey, ez, -nx, -ny, -nz, depth2, false);
- }
- }
- break;
- }
- };
- OIMO.SphereCylinderCollisionDetector = function (flip) {
- OIMO.CollisionDetector.call(this);
- this.flip = flip;
- };
- OIMO.SphereCylinderCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.SphereCylinderCollisionDetector.prototype.constructor = OIMO.SphereCylinderCollisionDetector;
- OIMO.SphereCylinderCollisionDetector.prototype.detectCollision = function (shape1, shape2, manifold) {
- var s;
- var c;
- if (this.flip) {
- s = shape2;
- c = shape1;
- } else {
- s = shape1;
- c = shape2;
- }
- var ps = s.position;
- var psx = ps.x;
- var psy = ps.y;
- var psz = ps.z;
- var pc = c.position;
- var pcx = pc.x;
- var pcy = pc.y;
- var pcz = pc.z;
- var dirx = c.normalDirection.x;
- var diry = c.normalDirection.y;
- var dirz = c.normalDirection.z;
- var rads = s.radius;
- var radc = c.radius;
- var rad2 = rads + radc;
- var halfh = c.halfHeight;
- var dx = psx - pcx;
- var dy = psy - pcy;
- var dz = psz - pcz;
- var dot = dx * dirx + dy * diry + dz * dirz;
- if (dot < -halfh - rads || dot > halfh + rads) return;
- var cx = pcx + dot * dirx;
- var cy = pcy + dot * diry;
- var cz = pcz + dot * dirz;
- var d2x = psx - cx;
- var d2y = psy - cy;
- var d2z = psz - cz;
- var len = d2x * d2x + d2y * d2y + d2z * d2z;
- if (len > rad2 * rad2) return;
- if (len > radc * radc) {
- len = radc / OIMO.sqrt(len);
- d2x *= len;
- d2y *= len;
- d2z *= len;
- }
- if (dot < -halfh) dot = -halfh;
- else if (dot > halfh) dot = halfh;
- cx = pcx + dot * dirx + d2x;
- cy = pcy + dot * diry + d2y;
- cz = pcz + dot * dirz + d2z;
- dx = cx - psx;
- dy = cy - psy;
- dz = cz - psz;
- len = dx * dx + dy * dy + dz * dz;
- var invLen;
- if (len > 0 && len < rads * rads) {
- len = OIMO.sqrt(len);
- invLen = 1 / len;
- dx *= invLen;
- dy *= invLen;
- dz *= invLen;
- ///result.addContactInfo(psx+dx*rads,psy+dy*rads,psz+dz*rads,dx,dy,dz,len-rads,s,c,0,0,false);
- manifold.addPoint(psx + dx * rads, psy + dy * rads, psz + dz * rads, dx, dy, dz, len - rads, this.flip);
- }
- };
- /**
- * Class for checking collisions between 2 tetras,
- * a shape that is made with 4 vertices and 4 faces
- * arranged in triangles. With this algorigthm, soft
- * body physics are possible and easier to implement.
- * @author xprogram
- */
- OIMO.TetraTetraCollisionDetector = function () {
- OIMO.CollisionDetector.call(this);
- };
- OIMO.TetraTetraCollisionDetector.prototype = Object.create(OIMO.CollisionDetector.prototype);
- OIMO.TetraTetraCollisionDetector.prototype.constructor = OIMO.TetraTetraCollisionDetector;
- OIMO.TetraTetraCollisionDetector.prototype.detectCollision = function (tet1, tet2, manifold) {
- /*
- * What we are doing:
- * Each tetra is represented by four 3D triangles. The only
- * quick way of finding if another tetra is within the other
- * tetra is to see if a single vertex is within the triangles
- * of the other tetra. So, for example, a tetra is represented
- * by points B, C, D and E with triangles BCD, BCE, DCE and BDE.
- * There is another tetra with a vertex A which was detected for
- * collision by the broadphase. Now, if the point A is between ALL
- * triangles of the other tetra (BCD, BCE, etc.) then the collision
- * is valid and we can pass point A to the manifold. Since the only
- * points on the tetra are the 4 vertices, collision detection is
- * not so complex. However, it can be time-consuming because we
- * need to split the 3D triangles into three 2D triangles each for
- * collision detection.
- */
- var i, j, vec, fs1 = tet1.faces, vs1 = tet1.verts, fs2 = tet2.faces, vs2 = tet2.verts;
- var j1, j2, j3, ts = 0; // Triangle vertices `j1`, `j2` and `j3`
- // fs is undeclared
- var fs = fs1;
- for (i = 0; i < 4; i++) {
- vec = vs1[i];
- for (j = 0; j < 4; j++) {
- j1 = vs2[fs[i].a];
- j2 = vs2[fs[i].b];
- j3 = vs2[fs[i].c];
- if (
- tricheck(pt(vec.x, vec.y), pt(j1.x, j1.y), pt(j2.x, j2.y), pt(j3.x, j3.y)) &&
- tricheck(pt(vec.x, vec.z), pt(j1.x, j1.z), pt(j2.x, j2.z), pt(j3.x, j3.z)) &&
- tricheck(pt(vec.z, vec.y), pt(j1.z, j1.y), pt(j2.z, j2.y), pt(j3.z, j3.y))
- )
- ts++;
- if (ts === 4) // Only add point if it is inside all 4 triangles
- manifold.addPoint(vec);
- }
- }
- };
- // Taken from: http://jsfiddle.net/PerroAZUL/zdaY8/1/
- function tricheck(p, p0, p1, p2) {
- var A = 0.5 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
- var sg = A < 0 ? -1 : 1;
- var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sg;
- var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sg;
- return s > 0 && t > 0 && (s + t) < 2 * A * sg;
- }
- function pt(x, y) { return { x: x, y: y }; }
- /**
- * An axis-aligned bounding box.
- * @author saharan
- * @author lo-th
- */
- OIMO.AABB = function (minX, maxX, minY, maxY, minZ, maxZ) {
- this.elements = new OIMO_ARRAY_TYPE(6);
- var te = this.elements;
- te[0] = minX || 0; te[1] = minY || 0; te[2] = minZ || 0;
- te[3] = maxX || 0; te[4] = maxY || 0; te[5] = maxZ || 0;
- };
- OIMO.AABB.prototype = {
- constructor: OIMO.AABB,
- set: function (minX, maxX, minY, maxY, minZ, maxZ) {
- var te = this.elements;
- te[0] = minX; te[3] = maxX;
- te[1] = minY; te[4] = maxY;
- te[2] = minZ; te[5] = maxZ;
- return this;
- },
- intersectTest: function (aabb) {
- var te = this.elements;
- var ue = aabb.elements;
- return te[0] > ue[3] || te[1] > ue[4] || te[2] > ue[5] || te[3] < ue[0] || te[4] < ue[1] || te[5] < ue[2];
- },
- intersectTestTwo: function (aabb) {
- var te = this.elements;
- var ue = aabb.elements;
- return te[0] < ue[0] || te[1] < ue[1] || te[2] < ue[2] || te[3] > ue[3] || te[4] > ue[4] || te[5] > ue[5];
- },
- clone: function () {
- return new this.constructor().fromArray(this.elements);
- },
- copy: function (aabb, margin) {
- var m = margin || 0;
- var me = aabb.elements;
- this.set(me[0] - m, me[3] + m, me[1] - m, me[4] + m, me[2] - m, me[5] + m);
- return this;
- },
- fromArray: function (array) {
- this.elements.set(array);
- return this;
- },
- // Set this AABB to the combined AABB of aabb1 and aabb2.
- combine: function (aabb1, aabb2) {
- var a = aabb1.elements;
- var b = aabb2.elements;
- var te = this.elements;
- te[0] = a[0] < b[0] ? a[0] : b[0];
- te[1] = a[1] < b[1] ? a[1] : b[1];
- te[2] = a[2] < b[2] ? a[2] : b[2];
- te[3] = a[3] > b[3] ? a[3] : b[3];
- te[4] = a[4] > b[4] ? a[4] : b[4];
- te[5] = a[5] > b[5] ? a[5] : b[5];
- return this;
- },
- // Get the surface area.
- surfaceArea: function () {
- var te = this.elements;
- var a = te[3] - te[0];
- var h = te[4] - te[1];
- var d = te[5] - te[2];
- return 2 * (a * (h + d) + h * d);
- },
- // Get whether the AABB intersects with the point or not.
- intersectsWithPoint: function (x, y, z) {
- var te = this.elements;
- return x >= te[0] && x <= te[3] && y >= te[1] && y <= te[4] && z >= te[2] && z <= te[5];
- },
- /**
- * Set the AABB from an array
- * of vertices. From THREE.
- * @author mrdoob
- * @author xprogram
- */
- setFromPoints: function (arr) {
- this.makeEmpty();
- for (var i = 0; i < arr.length; i++) {
- this.expandByPoint(arr[i]);
- }
- },
- makeEmpty: function () {
- this.set(-Infinity, -Infinity, -Infinity, Infinity, Infinity, Infinity);
- },
- expandByPoint: function (pt) {
- var te = this.elements;
- this.set(
- OIMO.min(te[0], pt.x), OIMO.min(te[1], pt.y), OIMO.min(te[2], pt.z),
- OIMO.max(te[3], pt.x), OIMO.max(te[4], pt.y), OIMO.max(te[5], pt.z)
- );
- }
- };
- /**
- * A proxy is used for broad-phase collecting pairs that can be colliding.
- */
- OIMO.Proxy = function (shape) {
- // The parent shape.
- this.shape = shape;
- // The axis-aligned bounding box.
- this.aabb = shape.aabb;
- };
- OIMO.Proxy.prototype = {
- constructor: OIMO.Proxy,
- // Update the proxy.
- update: function () {
- OIMO.Error("Proxy", "Inheritance error.");
- }
- };
- /**
- * A basic implementation of proxies.
- * @author saharan
- */
- OIMO.BasicProxy = function (shape) {
- OIMO.Proxy.call(this, shape);
- this.id = OIMO.proxyID++;
- };
- OIMO.BasicProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.BasicProxy.prototype.constructor = OIMO.BasicProxy;
- OIMO.BasicProxy.prototype.update = function () {
- };
- /**
- * The broad-phase is used for collecting all possible pairs for collision.
- */
- OIMO.BroadPhase = function () {
- this.types = OIMO.BR_NULL;
- this.numPairChecks = 0;
- this.numPairs = 0;
- this.pairs = [];
- };
- OIMO.BroadPhase.prototype = {
- constructor: OIMO.BroadPhase,
- /**
- * Create a new proxy.
- * @param shape
- * @return
- */
- createProxy: function (shape) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Add the proxy into the broad-phase.
- * @param proxy
- */
- addProxy: function (proxy) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Remove the proxy from the broad-phase.
- * @param proxy
- */
- removeProxy: function (proxy) {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- /**
- * Returns whether the pair is available or not.
- * @param s1
- * @param s2
- * @return
- */
- isAvailablePair: function (s1, s2) {
- var b1 = s1.parent;
- var b2 = s2.parent;
- if (b1 == b2 || // same parents
- (!b1.isDynamic && !b2.isDynamic) || // static or kinematic object
- (s1.belongsTo & s2.collidesWith) == 0 ||
- (s2.belongsTo & s1.collidesWith) == 0 // collision filtering
- ) { return false; }
- var js;
- if (b1.numJoints < b2.numJoints) js = b1.jointLink;
- else js = b2.jointLink;
- while (js !== null) {
- var joint = js.joint;
- if (!joint.allowCollision && ((joint.body1 == b1 && joint.body2 == b2) || (joint.body1 == b2 && joint.body2 == b1))) { return false; }
- js = js.next;
- }
- return true;
- },
- // Detect overlapping pairs.
- detectPairs: function () {
- // clear old
- this.pairs = [];
- this.numPairs = 0;
- this.numPairChecks = 0;
- this.collectPairs();
- },
- collectPairs: function () {
- OIMO.Error("BroadPhase", "Inheritance error.");
- },
- addPair: function (s1, s2) {
- var pair = new OIMO.Pair(s1, s2);
- this.pairs.push(pair);
- this.numPairs++;
- }
- };
- /**
- * A broad-phase algorithm with brute-force search.
- * This always checks for all possible pairs.
- */
- OIMO.BruteForceBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_BRUTE_FORCE;;
- //this.numProxies=0;
- ///this.maxProxies = 256;
- this.proxies = [];
- //this.proxies.length = 256;
- };
- OIMO.BruteForceBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.BruteForceBroadPhase.prototype.constructor = OIMO.BruteForceBroadPhase;
- OIMO.BruteForceBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.BasicProxy(shape);
- };
- OIMO.BruteForceBroadPhase.prototype.addProxy = function (proxy) {
- /*if(this.numProxies==this.maxProxies){
- //this.maxProxies<<=1;
- this.maxProxies*=2;
- var newProxies=[];
- newProxies.length = this.maxProxies;
- var i = this.numProxies;
- while(i--){
- //for(var i=0, l=this.numProxies;i<l;i++){
- newProxies[i]=this.proxies[i];
- }
- this.proxies=newProxies;
- }*/
- //this.proxies[this.numProxies++] = proxy;
- this.proxies.push(proxy);
- //this.numProxies++;
- };
- OIMO.BruteForceBroadPhase.prototype.removeProxy = function (proxy) {
- var n = this.proxies.indexOf(proxy);
- if (n > -1) {
- this.proxies.splice(n, 1);
- //this.numProxies--;
- }
- /*var i = this.numProxies;
- while(i--){
- //for(var i=0, l=this.numProxies;i<l;i++){
- if(this.proxies[i] == proxy){
- this.proxies[i] = this.proxies[--this.numProxies];
- this.proxies[this.numProxies] = null;
- return;
- }
- }*/
- };
- OIMO.BruteForceBroadPhase.prototype.collectPairs = function () {
- var i = 0, j, p1, p2;
- var px = this.proxies;
- var l = px.length;//this.numProxies;
- //var ar1 = [];
- //var ar2 = [];
- //for( i = px.length ; i-- ; ar1[ i ] = px[ i ] ){};
- //for( i = px.length ; i-- ; ar2[ i ] = px[ i ] ){};
- //var ar1 = JSON.parse(JSON.stringify(this.proxies))
- //var ar2 = JSON.parse(JSON.stringify(this.proxies))
- this.numPairChecks = l * (l - 1) >> 1;
- //this.numPairChecks=this.numProxies*(this.numProxies-1)*0.5;
- while (i < l) {
- p1 = px[i++];
- j = i + 1;
- while (j < l) {
- p2 = px[j++];
- if (p1.aabb.intersectTest(p2.aabb) || !this.isAvailablePair(p1.shape, p2.shape)) continue;
- this.addPair(p1.shape, p2.shape);
- }
- }
- };
- /**
- * A pair of shapes that may collide.
- * @author saharan
- */
- OIMO.Pair = function (s1, s2) {
- // The first shape.
- this.shape1 = s1 || null;
- // The second shape.
- this.shape2 = s2 || null;
- };
- /**
- * A projection axis for sweep and prune broad-phase.
- * @author saharan
- */
- OIMO.SAPAxis = function () {
- this.numElements = 0;
- this.bufferSize = 256;
- this.elements = [];
- this.elements.length = this.bufferSize;
- this.stack = new OIMO_ARRAY_TYPE(64);
- };
- OIMO.SAPAxis.prototype = {
- constructor: OIMO.SAPAxis,
- addElements: function (min, max) {
- if (this.numElements + 2 >= this.bufferSize) {
- //this.bufferSize<<=1;
- this.bufferSize *= 2;
- var newElements = [];
- var i = this.numElements;
- while (i--) {
- //for(var i=0, l=this.numElements; i<l; i++){
- newElements[i] = this.elements[i];
- }
- }
- this.elements[this.numElements++] = min;
- this.elements[this.numElements++] = max;
- },
- removeElements: function (min, max) {
- var minIndex = -1;
- var maxIndex = -1;
- for (var i = 0, l = this.numElements; i < l; i++) {
- var e = this.elements[i];
- if (e == min || e == max) {
- if (minIndex == -1) {
- minIndex = i;
- } else {
- maxIndex = i;
- break;
- }
- }
- }
- for (i = minIndex + 1, l = maxIndex; i < l; i++) {
- this.elements[i - 1] = this.elements[i];
- }
- for (i = maxIndex + 1, l = this.numElements; i < l; i++) {
- this.elements[i - 2] = this.elements[i];
- }
- this.elements[--this.numElements] = null;
- this.elements[--this.numElements] = null;
- },
- sort: function () {
- var count = 0;
- var threshold = 1;
- while ((this.numElements >> threshold) != 0) threshold++;
- threshold = threshold * this.numElements >> 2;
- count = 0;
- var giveup = false;
- var elements = this.elements;
- for (var i = 1, l = this.numElements; i < l; i++) { // try insertion sort
- var tmp = elements[i];
- var pivot = tmp.value;
- var tmp2 = elements[i - 1];
- if (tmp2.value > pivot) {
- var j = i;
- do {
- elements[j] = tmp2;
- if (--j == 0) break;
- tmp2 = elements[j - 1];
- } while (tmp2.value > pivot);
- elements[j] = tmp;
- count += i - j;
- if (count > threshold) {
- giveup = true; // stop and use quick sort
- break;
- }
- }
- }
- if (!giveup) return;
- count = 2; var stack = this.stack;
- stack[0] = 0;
- stack[1] = this.numElements - 1;
- while (count > 0) {
- var right = stack[--count];
- var left = stack[--count];
- var diff = right - left;
- if (diff > 16) { // quick sort
- //var mid=left+(diff>>1);
- var mid = left + (OIMO.floor(diff * 0.5));
- tmp = elements[mid];
- elements[mid] = elements[right];
- elements[right] = tmp;
- pivot = tmp.value;
- i = left - 1;
- j = right;
- while (true) {
- var ei;
- var ej;
- do { ei = elements[++i]; } while (ei.value < pivot);
- do { ej = elements[--j]; } while (pivot < ej.value && j != left);
- if (i >= j) break;
- elements[i] = ej;
- elements[j] = ei;
- }
- elements[right] = elements[i];
- elements[i] = tmp;
- if (i - left > right - i) {
- stack[count++] = left;
- stack[count++] = i - 1;
- stack[count++] = i + 1;
- stack[count++] = right;
- } else {
- stack[count++] = i + 1;
- stack[count++] = right;
- stack[count++] = left;
- stack[count++] = i - 1;
- }
- } else {
- for (i = left + 1; i <= right; i++) {
- tmp = elements[i];
- pivot = tmp.value;
- tmp2 = elements[i - 1];
- if (tmp2.value > pivot) {
- j = i;
- do {
- elements[j] = tmp2;
- if (--j == 0) break;
- tmp2 = elements[j - 1];
- } while (tmp2.value > pivot);
- elements[j] = tmp;
- }
- }
- }
- }
- },
- calculateTestCount: function () {
- var num = 1;
- var sum = 0;
- for (var i = 1, l = this.numElements; i < l; i++) {
- if (this.elements[i].max) {
- num--;
- } else {
- sum += num;
- num++;
- }
- }
- return sum;
- }
- }
- /**
- * A broad-phase collision detection algorithm using sweep and prune.
- * @author saharan
- * @author lo-th
- */
- OIMO.SAPBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_SWEEP_AND_PRUNE;
- this.numElementsD = 0;
- this.numElementsS = 0;
- // dynamic proxies
- this.axesD = [
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis()
- ];
- // static or sleeping proxies
- this.axesS = [
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis(),
- new OIMO.SAPAxis()
- ];
- this.index1 = 0;
- this.index2 = 1;
- };
- OIMO.SAPBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.SAPBroadPhase.prototype.constructor = OIMO.SAPBroadPhase;
- OIMO.SAPBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.SAPProxy(this, shape);
- };
- OIMO.SAPBroadPhase.prototype.addProxy = function (proxy) {
- var p = proxy;
- if (p.isDynamic()) {
- this.axesD[0].addElements(p.min[0], p.max[0]);
- this.axesD[1].addElements(p.min[1], p.max[1]);
- this.axesD[2].addElements(p.min[2], p.max[2]);
- p.belongsTo = 1;
- this.numElementsD += 2;
- } else {
- this.axesS[0].addElements(p.min[0], p.max[0]);
- this.axesS[1].addElements(p.min[1], p.max[1]);
- this.axesS[2].addElements(p.min[2], p.max[2]);
- p.belongsTo = 2;
- this.numElementsS += 2;
- }
- };
- OIMO.SAPBroadPhase.prototype.removeProxy = function (proxy) {
- var p = proxy;
- if (p.belongsTo == 0) return;
- /*else if ( p.belongsTo == 1 ) {
- this.axesD[0].removeElements( p.min[0], p.max[0] );
- this.axesD[1].removeElements( p.min[1], p.max[1] );
- this.axesD[2].removeElements( p.min[2], p.max[2] );
- this.numElementsD -= 2;
- } else if ( p.belongsTo == 2 ) {
- this.axesS[0].removeElements( p.min[0], p.max[0] );
- this.axesS[1].removeElements( p.min[1], p.max[1] );
- this.axesS[2].removeElements( p.min[2], p.max[2] );
- this.numElementsS -= 2;
- }*/
- switch (p.belongsTo) {
- case 1:
- this.axesD[0].removeElements(p.min[0], p.max[0]);
- this.axesD[1].removeElements(p.min[1], p.max[1]);
- this.axesD[2].removeElements(p.min[2], p.max[2]);
- this.numElementsD -= 2;
- break;
- case 2:
- this.axesS[0].removeElements(p.min[0], p.max[0]);
- this.axesS[1].removeElements(p.min[1], p.max[1]);
- this.axesS[2].removeElements(p.min[2], p.max[2]);
- this.numElementsS -= 2;
- break;
- }
- p.belongsTo = 0;
- };
- OIMO.SAPBroadPhase.prototype.collectPairs = function () {
- if (this.numElementsD == 0) return;
- var axis1 = this.axesD[this.index1];
- var axis2 = this.axesD[this.index2];
- axis1.sort();
- axis2.sort();
- var count1 = axis1.calculateTestCount();
- var count2 = axis2.calculateTestCount();
- var elementsD;
- var elementsS;
- if (count1 <= count2) {// select the best axis
- axis2 = this.axesS[this.index1];
- axis2.sort();
- elementsD = axis1.elements;
- elementsS = axis2.elements;
- } else {
- axis1 = this.axesS[this.index2];
- axis1.sort();
- elementsD = axis2.elements;
- elementsS = axis1.elements;
- this.index1 ^= this.index2;
- this.index2 ^= this.index1;
- this.index1 ^= this.index2;
- }
- var activeD;
- var activeS;
- var p = 0;
- var q = 0;
- while (p < this.numElementsD) {
- var e1;
- var dyn;
- if (q == this.numElementsS) {
- e1 = elementsD[p];
- dyn = true;
- p++;
- } else {
- var d = elementsD[p];
- var s = elementsS[q];
- if (d.value < s.value) {
- e1 = d;
- dyn = true;
- p++;
- } else {
- e1 = s;
- dyn = false;
- q++;
- }
- }
- if (!e1.max) {
- var s1 = e1.proxy.shape;
- var min1 = e1.min1.value;
- var max1 = e1.max1.value;
- var min2 = e1.min2.value;
- var max2 = e1.max2.value;
- for (var e2 = activeD; e2 != null; e2 = e2.pair) {// test for dynamic
- var s2 = e2.proxy.shape;
- this.numPairChecks++;
- if (min1 > e2.max1.value || max1 < e2.min1.value || min2 > e2.max2.value || max2 < e2.min2.value || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- }
- if (dyn) {
- for (e2 = activeS; e2 != null; e2 = e2.pair) {// test for static
- s2 = e2.proxy.shape;
- this.numPairChecks++;
- if (min1 > e2.max1.value || max1 < e2.min1.value || min2 > e2.max2.value || max2 < e2.min2.value || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- }
- e1.pair = activeD;
- activeD = e1;
- } else {
- e1.pair = activeS;
- activeS = e1;
- }
- } else {
- var min = e1.pair;
- if (dyn) {
- if (min == activeD) {
- activeD = activeD.pair;
- continue;
- } else {
- e1 = activeD;
- }
- } else {
- if (min == activeS) {
- activeS = activeS.pair;
- continue;
- } else {
- e1 = activeS;
- }
- }
- do {
- e2 = e1.pair;
- if (e2 == min) {
- e1.pair = e2.pair;
- break;
- }
- e1 = e2;
- } while (e1 != null);
- }
- }
- this.index2 = (this.index1 | this.index2) ^ 3;
- };
- /**
- * An element of proxies.
- * @author saharan
- */
- OIMO.SAPElement = function (proxy, max) {
- // The parent proxy
- this.proxy = proxy;
- // The pair element.
- this.pair = null;
- // The minimum element on other axis.
- this.min1 = null;
- // The maximum element on other axis.
- this.max1 = null;
- // The minimum element on other axis.
- this.min2 = null;
- // The maximum element on other axis.
- this.max2 = null;
- // Whether the element has maximum value or not.
- this.max = max;
- // The value of the element.
- this.value = 0;
- };
- /**
- * A proxy for sweep and prune broad-phase.
- * @author saharan
- * @author lo-th
- */
- OIMO.SAPProxy = function (sap, shape) {
- OIMO.Proxy.call(this, shape);
- // Type of the axis to which the proxy belongs to. [0:none, 1:dynamic, 2:static]
- this.belongsTo = 0;
- // The maximum elements on each axis.
- this.max = [];
- // The minimum elements on each axis.
- this.min = [];
- this.sap = sap;
- this.min[0] = new OIMO.SAPElement(this, false);
- this.max[0] = new OIMO.SAPElement(this, true);
- this.min[1] = new OIMO.SAPElement(this, false);
- this.max[1] = new OIMO.SAPElement(this, true);
- this.min[2] = new OIMO.SAPElement(this, false);
- this.max[2] = new OIMO.SAPElement(this, true);
- this.max[0].pair = this.min[0];
- this.max[1].pair = this.min[1];
- this.max[2].pair = this.min[2];
- this.min[0].min1 = this.min[1];
- this.min[0].max1 = this.max[1];
- this.min[0].min2 = this.min[2];
- this.min[0].max2 = this.max[2];
- this.min[1].min1 = this.min[0];
- this.min[1].max1 = this.max[0];
- this.min[1].min2 = this.min[2];
- this.min[1].max2 = this.max[2];
- this.min[2].min1 = this.min[0];
- this.min[2].max1 = this.max[0];
- this.min[2].min2 = this.min[1];
- this.min[2].max2 = this.max[1];
- };
- OIMO.SAPProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.SAPProxy.prototype.constructor = OIMO.SAPProxy;
- // Returns whether the proxy is dynamic or not.
- OIMO.SAPProxy.prototype.isDynamic = function () {
- var body = this.shape.parent;
- return body.isDynamic && !body.sleeping;
- };
- OIMO.SAPProxy.prototype.update = function () {
- var te = this.aabb.elements;
- this.min[0].value = te[0];
- this.min[1].value = te[1];
- this.min[2].value = te[2];
- this.max[0].value = te[3];
- this.max[1].value = te[4];
- this.max[2].value = te[5];
- if (this.belongsTo == 1 && !this.isDynamic() || this.belongsTo == 2 && this.isDynamic()) {
- this.sap.removeProxy(this);
- this.sap.addProxy(this);
- }
- };
- /**
- * A dynamic bounding volume tree for the broad-phase algorithm.
- * @author saharan
- * @author lo-th
- */
- OIMO.DBVT = function () {
- // The root of the tree.
- this.root = null;
- this.freeNodes = [];
- this.freeNodes.length = 16384;
- this.numFreeNodes = 0;
- this.aabb = new OIMO.AABB();
- };
- OIMO.DBVT.prototype = {
- constructor: OIMO.DBVT,
- /**
- * Move a leaf.
- * @param leaf
- */
- moveLeaf: function (leaf) {
- this.deleteLeaf(leaf);
- this.insertLeaf(leaf);
- },
- /**
- * Insert a leaf to the tree.
- * @param node
- */
- insertLeaf: function (leaf) {
- if (this.root == null) {
- this.root = leaf;
- return;
- }
- var lb = leaf.aabb;
- var sibling = this.root;
- var oldArea;
- var newArea;
- while (sibling.proxy == null) { // descend the node to search the best pair
- var c1 = sibling.child1;
- var c2 = sibling.child2;
- var b = sibling.aabb;
- var c1b = c1.aabb;
- var c2b = c2.aabb;
- oldArea = b.surfaceArea();
- this.aabb.combine(lb, b);
- newArea = this.aabb.surfaceArea();
- var creatingCost = newArea * 2;
- var incrementalCost = (newArea - oldArea) * 2; // cost of creating a new pair with the node
- var discendingCost1 = incrementalCost;
- this.aabb.combine(lb, c1b);
- if (c1.proxy != null) {
- // leaf cost = area(combined aabb)
- discendingCost1 += this.aabb.surfaceArea();
- } else {
- // node cost = area(combined aabb) - area(old aabb)
- discendingCost1 += this.aabb.surfaceArea() - c1b.surfaceArea();
- }
- var discendingCost2 = incrementalCost;
- this.aabb.combine(lb, c2b);
- if (c2.proxy != null) {
- // leaf cost = area(combined aabb)
- discendingCost2 += this.aabb.surfaceArea();
- } else {
- // node cost = area(combined aabb) - area(old aabb)
- discendingCost2 += this.aabb.surfaceArea() - c2b.surfaceArea();
- }
- if (discendingCost1 < discendingCost2) {
- if (creatingCost < discendingCost1) {
- break;// stop descending
- } else {
- sibling = c1;// descend into first child
- }
- } else {
- if (creatingCost < discendingCost2) {
- break;// stop descending
- } else {
- sibling = c2;// descend into second child
- }
- }
- }
- var oldParent = sibling.parent;
- var newParent;
- if (this.numFreeNodes > 0) {
- newParent = this.freeNodes[--this.numFreeNodes];
- } else {
- newParent = new OIMO.DBVTNode();
- }
- newParent.parent = oldParent;
- newParent.child1 = leaf;
- newParent.child2 = sibling;
- newParent.aabb.combine(leaf.aabb, sibling.aabb);
- newParent.height = sibling.height + 1;
- sibling.parent = newParent;
- leaf.parent = newParent;
- if (sibling == this.root) {
- // replace root
- this.root = newParent;
- } else {
- // replace child
- if (oldParent.child1 == sibling) {
- oldParent.child1 = newParent;
- } else {
- oldParent.child2 = newParent;
- }
- }
- // update whole tree
- do {
- newParent = this.balance(newParent);
- this.fix(newParent);
- newParent = newParent.parent;
- } while (newParent != null);
- },
- getBalance: function (node) {
- if (node.proxy != null) return 0;
- return node.child1.height - node.child2.height;
- },
- /*print:function(node,indent,text){
- var hasChild=node.proxy==null;
- if(hasChild)text=this.print(node.child1,indent+1,text);
- for(var i=indent*2;i>=0;i--){
- text+=" ";
- }
- text+=(hasChild?this.getBalance(node):"["+node.proxy.aabb.minX+"]")+"\n";
- if(hasChild)text=this.print(node.child2,indent+1,text);
- return text;
- },*/
- /**
- * Delete a leaf from the tree.
- * @param node
- */
- deleteLeaf: function (leaf) {
- if (leaf == this.root) {
- this.root = null;
- return;
- }
- var parent = leaf.parent;
- var sibling;
- if (parent.child1 == leaf) {
- sibling = parent.child2;
- } else {
- sibling = parent.child1;
- }
- if (parent == this.root) {
- this.root = sibling;
- sibling.parent = null;
- return;
- }
- var grandParent = parent.parent;
- sibling.parent = grandParent;
- if (grandParent.child1 == parent) {
- grandParent.child1 = sibling;
- } else {
- grandParent.child2 = sibling;
- }
- if (this.numFreeNodes < 16384) {
- this.freeNodes[this.numFreeNodes++] = parent;
- }
- do {
- grandParent = this.balance(grandParent);
- this.fix(grandParent);
- grandParent = grandParent.parent;
- } while (grandParent != null);
- },
- balance: function (node) {
- var nh = node.height;
- if (nh < 2) {
- return node;
- }
- var p = node.parent;
- var l = node.child1;
- var r = node.child2;
- var lh = l.height;
- var rh = r.height;
- var balance = lh - rh;
- var t;// for bit operation
- // [ N ]
- // / \
- // [ L ] [ R ]
- // / \ / \
- // [L-L] [L-R] [R-L] [R-R]
- // Is the tree balanced?
- if (balance > 1) {
- var ll = l.child1;
- var lr = l.child2;
- var llh = ll.height;
- var lrh = lr.height;
- // Is L-L higher than L-R?
- if (llh > lrh) {
- // set N to L-R
- l.child2 = node;
- node.parent = l;
- // [ L ]
- // / \
- // [L-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [ R ]
- // set L-R
- node.child1 = lr;
- lr.parent = node;
- // [ L ]
- // / \
- // [L-L] [ N ]
- // / \ / \
- // [...] [...] [L-R] [ R ]
- // fix bounds and heights
- node.aabb.combine(lr.aabb, r.aabb);
- t = lrh - rh;
- node.height = lrh - (t & t >> 31) + 1;
- l.aabb.combine(ll.aabb, node.aabb);
- t = llh - nh;
- l.height = llh - (t & t >> 31) + 1;
- } else {
- // set N to L-L
- l.child1 = node;
- node.parent = l;
- // [ L ]
- // / \
- // [ N ] [L-R]
- // / \ / \
- // [ L ] [ R ] [...] [...]
- // set L-L
- node.child1 = ll;
- ll.parent = node;
- // [ L ]
- // / \
- // [ N ] [L-R]
- // / \ / \
- // [L-L] [ R ] [...] [...]
- // fix bounds and heights
- node.aabb.combine(ll.aabb, r.aabb);
- t = llh - rh;
- node.height = llh - (t & t >> 31) + 1;
- l.aabb.combine(node.aabb, lr.aabb);
- t = nh - lrh;
- l.height = nh - (t & t >> 31) + 1;
- }
- // set new parent of L
- if (p != null) {
- if (p.child1 == node) {
- p.child1 = l;
- } else {
- p.child2 = l;
- }
- } else {
- this.root = l;
- }
- l.parent = p;
- return l;
- } else if (balance < -1) {
- var rl = r.child1;
- var rr = r.child2;
- var rlh = rl.height;
- var rrh = rr.height;
- // Is R-L higher than R-R?
- if (rlh > rrh) {
- // set N to R-R
- r.child2 = node;
- node.parent = r;
- // [ R ]
- // / \
- // [R-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [ R ]
- // set R-R
- node.child2 = rr;
- rr.parent = node;
- // [ R ]
- // / \
- // [R-L] [ N ]
- // / \ / \
- // [...] [...] [ L ] [R-R]
- // fix bounds and heights
- node.aabb.combine(l.aabb, rr.aabb);
- t = lh - rrh;
- node.height = lh - (t & t >> 31) + 1;
- r.aabb.combine(rl.aabb, node.aabb);
- t = rlh - nh;
- r.height = rlh - (t & t >> 31) + 1;
- } else {
- // set N to R-L
- r.child1 = node;
- node.parent = r;
- // [ R ]
- // / \
- // [ N ] [R-R]
- // / \ / \
- // [ L ] [ R ] [...] [...]
- // set R-L
- node.child2 = rl;
- rl.parent = node;
- // [ R ]
- // / \
- // [ N ] [R-R]
- // / \ / \
- // [ L ] [R-L] [...] [...]
- // fix bounds and heights
- node.aabb.combine(l.aabb, rl.aabb);
- t = lh - rlh;
- node.height = lh - (t & t >> 31) + 1;
- r.aabb.combine(node.aabb, rr.aabb);
- t = nh - rrh;
- r.height = nh - (t & t >> 31) + 1;
- }
- // set new parent of R
- if (p != null) {
- if (p.child1 == node) {
- p.child1 = r;
- } else {
- p.child2 = r;
- }
- } else {
- this.root = r;
- }
- r.parent = p;
- return r;
- }
- return node;
- },
- fix: function (node) {
- var c1 = node.child1;
- var c2 = node.child2;
- node.aabb.combine(c1.aabb, c2.aabb);
- //var h1 = c1.height;
- //var h2 = c2.height;
- node.height = c1.height < c2.height ? c2.height + 1 : c1.height + 1;
- /*if( h1 < h2 ) {
- node.height = h2+1;
- }else{
- node.height = h1+1;
- }*/
- }
- }
- /**
- * A broad-phase algorithm using dynamic bounding volume tree.
- * @author saharan
- * @author lo-th
- */
- OIMO.DBVTBroadPhase = function () {
- OIMO.BroadPhase.call(this);
- this.types = OIMO.BR_BOUNDING_VOLUME_TREE;
- this.tree = new OIMO.DBVT();
- this.stack = [];
- this.leaves = [];
- this.numLeaves = 0;
- };
- OIMO.DBVTBroadPhase.prototype = Object.create(OIMO.BroadPhase.prototype);
- OIMO.DBVTBroadPhase.prototype.constructor = OIMO.DBVTBroadPhase;
- OIMO.DBVTBroadPhase.prototype.createProxy = function (shape) {
- return new OIMO.DBVTProxy(shape);
- };
- OIMO.DBVTBroadPhase.prototype.addProxy = function (proxy) {
- this.tree.insertLeaf(proxy.leaf);
- this.leaves.push(proxy.leaf);
- this.numLeaves++;
- };
- OIMO.DBVTBroadPhase.prototype.removeProxy = function (proxy) {
- this.tree.deleteLeaf(proxy.leaf);
- var n = this.leaves.indexOf(proxy.leaf);
- if (n > -1) {
- this.leaves.splice(n, 1);
- this.numLeaves--;
- }
- };
- OIMO.DBVTBroadPhase.prototype.collectPairs = function () {
- if (this.numLeaves < 2) return;
- var leaf, margin = 0.1, i = this.numLeaves;
- while (i--) {
- leaf = this.leaves[i];
- if (leaf.proxy.aabb.intersectTestTwo(leaf.aabb)) {
- leaf.aabb.copy(leaf.proxy.aabb, margin);
- this.tree.deleteLeaf(leaf);
- this.tree.insertLeaf(leaf);
- this.collide(leaf, this.tree.root);
- }
- }
- };
- OIMO.DBVTBroadPhase.prototype.collide = function (node1, node2) {
- var stackCount = 2;
- var s1, s2, n1, n2, l1, l2;
- this.stack[0] = node1;
- this.stack[1] = node2;
- while (stackCount > 0) {
- n1 = this.stack[--stackCount];
- n2 = this.stack[--stackCount];
- l1 = n1.proxy != null;
- l2 = n2.proxy != null;
- this.numPairChecks++;
- if (l1 && l2) {
- s1 = n1.proxy.shape;
- s2 = n2.proxy.shape;
- if (s1 == s2 || s1.aabb.intersectTest(s2.aabb) || !this.isAvailablePair(s1, s2)) continue;
- this.addPair(s1, s2);
- } else {
- if (n1.aabb.intersectTest(n2.aabb)) continue;
- /*if(stackCount+4>=this.maxStack){// expand the stack
- //this.maxStack<<=1;
- this.maxStack*=2;
- var newStack = [];// vector
- newStack.length = this.maxStack;
- for(var i=0;i<stackCount;i++){
- newStack[i] = this.stack[i];
- }
- this.stack = newStack;
- }*/
- if (l2 || !l1 && (n1.aabb.surfaceArea() > n2.aabb.surfaceArea())) {
- this.stack[stackCount++] = n1.child1;
- this.stack[stackCount++] = n2;
- this.stack[stackCount++] = n1.child2;
- this.stack[stackCount++] = n2;
- } else {
- this.stack[stackCount++] = n1;
- this.stack[stackCount++] = n2.child1;
- this.stack[stackCount++] = n1;
- this.stack[stackCount++] = n2.child2;
- }
- }
- }
- };
- /**
- * A node of the dynamic bounding volume tree.
- * @author saharan
- */
- OIMO.DBVTNode = function () {
- // The first child node of this node.
- this.child1 = null;
- // The second child node of this node.
- this.child2 = null;
- // The parent node of this tree.
- this.parent = null;
- // The proxy of this node. This has no value if this node is not leaf.
- this.proxy = null;
- // The maximum distance from leaf nodes.
- this.height = 0;
- // The AABB of this node.
- this.aabb = new OIMO.AABB();
- };
- /**
- * A proxy for dynamic bounding volume tree broad-phase.
- * @author saharan
- */
- OIMO.DBVTProxy = function (shape) {
- OIMO.Proxy.call(this, shape);
- // The leaf of the proxy.
- this.leaf = new OIMO.DBVTNode();
- this.leaf.proxy = this;
- };
- OIMO.DBVTProxy.prototype = Object.create(OIMO.Proxy.prototype);
- OIMO.DBVTProxy.prototype.constructor = OIMO.DBVTProxy;
- OIMO.DBVTProxy.prototype.update = function () {
- };
- OIMO.World.prototype.add = function (obj) {
- obj = obj || {};
- var type = obj.type || "box";
- if (typeof type === 'string') type = [type];// single shape
- if (type[0].substring(0, 5) == 'joint') { // is joint
- if (type[0] === 'joint') type[0] = 'jointHinge';
- var axe1 = obj.axe1 || [1, 0, 0];
- var axe2 = obj.axe2 || [1, 0, 0];
- var pos1 = obj.pos1 || [0, 0, 0];
- var pos2 = obj.pos2 || [0, 0, 0];
- pos1 = pos1.map(function (x) { return x * OIMO.INV_SCALE; });
- pos2 = pos2.map(function (x) { return x * OIMO.INV_SCALE; });
- var min, max;
- if (type[0] === "jointDistance") {
- min = obj.min || 0;
- max = obj.max || 10;
- min = min * OIMO.INV_SCALE;
- max = max * OIMO.INV_SCALE;
- } else {
- min = obj.min || 57.29578;
- max = obj.max || 0;
- min = min * OIMO.degtorad;
- max = max * OIMO.degtorad;
- }
- var limit = obj.limit || null;
- var spring = obj.spring || null;
- var motor = obj.motor || null;
- // joint setting
- var jc = new OIMO.JointConfig();
- jc.allowCollision = obj.collision || false;;
- jc.localAxis1.init(axe1[0], axe1[1], axe1[2]);
- jc.localAxis2.init(axe2[0], axe2[1], axe2[2]);
- jc.localAnchorPoint1.init(pos1[0], pos1[1], pos1[2]);
- jc.localAnchorPoint2.init(pos2[0], pos2[1], pos2[2]);
- if (typeof obj.body1 == 'string' || obj.body1 instanceof String) obj.body1 = this.getByName(obj.body1);
- if (typeof obj.body2 == 'string' || obj.body2 instanceof String) obj.body2 = this.getByName(obj.body2);
- jc.body1 = obj.body1;
- jc.body2 = obj.body2;
- var joint;
- switch (type[0]) {
- case "jointDistance": joint = new OIMO.DistanceJoint(jc, min, max);
- if (spring !== null) joint.limitMotor.setSpring(spring[0], spring[1]);
- if (motor !== null) joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointHinge": joint = new OIMO.HingeJoint(jc, min, max);
- if (spring !== null) joint.limitMotor.setSpring(spring[0], spring[1]);// soften the joint ex: 100, 0.2
- if (motor !== null) joint.limitMotor.setSpring(motor[0], motor[1]);
- break;
- case "jointPrisme": joint = new OIMO.PrismaticJoint(jc, min, max); break;
- case "jointSlide": joint = new OIMO.SliderJoint(jc, min, max); break;
- case "jointBall": joint = new OIMO.BallAndSocketJoint(jc); break;
- case "jointWheel": joint = new OIMO.WheelJoint(jc);
- if (limit !== null) joint.rotationalLimitMotor1.setLimit(limit[0], limit[1]);
- if (spring !== null) joint.rotationalLimitMotor1.setSpring(spring[0], spring[1]);
- if (motor !== null) joint.rotationalLimitMotor1.setSpring(motor[0], motor[1]);
- break;
- }
- joint.name = obj.name || '';
- // finaly add to physics world
- this.addJoint(joint);
- return joint;
- } else { // is body
- // I'm dynamique or not
- var move = obj.move || false;
- // I can sleep or not
- var noSleep = obj.noSleep || false;
- // My start position
- var p = obj.pos || [0, 0, 0];
- p = p.map(function (x) { return x * OIMO.INV_SCALE; });
- // My size
- var s = obj.size || [1, 1, 1];
- s = s.map(function (x) { return x * OIMO.INV_SCALE; });
- // My rotation in degre
- var rot = obj.rot || [0, 0, 0];
- rot = rot.map(function (x) { return x * OIMO.degtorad; });
- var r = [];
- for (var i = 0; i < rot.length / 3; i++) {
- var tmp = OIMO.EulerToAxis(rot[i + 0], rot[i + 1], rot[i + 2]);
- r.push(tmp[0]); r.push(tmp[1]); r.push(tmp[2]); r.push(tmp[3]);
- }
- // My physics setting
- var sc = new OIMO.ShapeConfig();
- if (obj.sc !== undefined) sc = obj.sc;
- if (obj.config) {
- // The density of the shape.
- sc.density = obj.config[0] === undefined ? 1 : obj.config[0];
- // The coefficient of friction of the shape.
- sc.friction = obj.config[1] === undefined ? 0.4 : obj.config[1];
- // The coefficient of restitution of the shape.
- sc.restitution = obj.config[2] === undefined ? 0.2 : obj.config[2];
- // The bits of the collision groups to which the shape belongs.
- sc.belongsTo = obj.config[3] || 1;
- //sc.belongsTo = obj.config[3] === undefined ? 1 : obj.config[3];
- // The bits of the collision groups with which the shape collides.
- sc.collidesWith = obj.config[4] || 0xffffffff;
- //sc.collidesWith = obj.config[4] === undefined ? 0xffffffff : obj.config[4];
- }
- // direct physics setting
- if (obj.density !== undefined) sc.density = obj.density;
- if (obj.friction !== undefined) sc.friction = obj.friction;
- if (obj.restitution !== undefined) sc.restitution = obj.restitution;
- if (obj.belongsTo !== undefined) sc.belongsTo = obj.belongsTo;
- if (obj.collidesWith !== undefined) sc.collidesWith = obj.collidesWith;
- if (obj.massPos) {
- obj.massPos = obj.massPos.map(function (x) { return x * OIMO.INV_SCALE; });
- sc.relativePosition.init(obj.massPos[0], obj.massPos[1], obj.massPos[2]);
- }
- if (obj.massRot) {
- obj.massRot = obj.massRot.map(function (x) { return x * OIMO.degtorad; });
- sc.relativeRotation = OIMO.EulerToMatrix(obj.massRot[0], obj.massRot[1], obj.massRot[2]);
- }
- // My rigidbody
- var body = new OIMO.RigidBody(p[0], p[1], p[2], r[0], r[1], r[2], r[3]);
- // My shapes
- var shapes = [];
- //if( typeof type === 'string' ) type = [type];// single shape
- var n, n2;
- for (var i = 0; i < type.length; i++) {
- n = i * 3;
- n2 = i * 4;
- switch (type[i]) {
- case "sphere": shapes[i] = new OIMO.SphereShape(sc, s[n]); break;
- case "cylinder": shapes[i] = new OIMO.CylinderShape(sc, s[n], s[n + 1]); break;
- case "box": shapes[i] = new OIMO.BoxShape(sc, s[n], s[n + 1], s[n + 2]); break;
- }
- body.addShape(shapes[i]);
- if (i > 0) {
- //shapes[i].position.init(p[0]+p[n+0], p[1]+p[n+1], p[2]+p[n+2] );
- shapes[i].relativePosition = new OIMO.Vec3(p[n], p[n + 1], p[n + 2]);
- if (r[n2 + 0]) shapes[i].relativeRotation = [r[n2], r[n2 + 1], r[n2 + 2], r[n2 + 3]];
- }
- }
- // I'm static or i move
- if (move) {
- if (obj.massPos || obj.massRot) body.setupMass(0x1, false);
- else body.setupMass(0x1, true);
- if (noSleep) body.allowSleep = false;
- else body.allowSleep = true;
- } else {
- body.setupMass(0x2);
- }
- body.name = obj.name || ' ';
- // finaly add to physics world
- this.addRigidBody(body);
- return body;
- }
- }
|