three.module.js 1.3 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568255692557025571255722557325574255752557625577255782557925580255812558225583255842558525586255872558825589255902559125592255932559425595255962559725598255992560025601256022560325604256052560625607256082560925610256112561225613256142561525616256172561825619256202562125622256232562425625256262562725628256292563025631256322563325634256352563625637256382563925640256412564225643256442564525646256472564825649256502565125652256532565425655256562565725658256592566025661256622566325664256652566625667256682566925670256712567225673256742567525676256772567825679256802568125682256832568425685256862568725688256892569025691256922569325694256952569625697256982569925700257012570225703257042570525706257072570825709257102571125712257132571425715257162571725718257192572025721257222572325724257252572625727257282572925730257312573225733257342573525736257372573825739257402574125742257432574425745257462574725748257492575025751257522575325754257552575625757257582575925760257612576225763257642576525766257672576825769257702577125772257732577425775257762577725778257792578025781257822578325784257852578625787257882578925790257912579225793257942579525796257972579825799258002580125802258032580425805258062580725808258092581025811258122581325814258152581625817258182581925820258212582225823258242582525826258272582825829258302583125832258332583425835258362583725838258392584025841258422584325844258452584625847258482584925850258512585225853258542585525856258572585825859258602586125862258632586425865258662586725868258692587025871258722587325874258752587625877258782587925880258812588225883258842588525886258872588825889258902589125892258932589425895258962589725898258992590025901259022590325904259052590625907259082590925910259112591225913259142591525916259172591825919259202592125922259232592425925259262592725928259292593025931259322593325934259352593625937259382593925940259412594225943259442594525946259472594825949259502595125952259532595425955259562595725958259592596025961259622596325964259652596625967259682596925970259712597225973259742597525976259772597825979259802598125982259832598425985259862598725988259892599025991259922599325994259952599625997259982599926000260012600226003260042600526006260072600826009260102601126012260132601426015260162601726018260192602026021260222602326024260252602626027260282602926030260312603226033260342603526036260372603826039260402604126042260432604426045260462604726048260492605026051260522605326054260552605626057260582605926060260612606226063260642606526066260672606826069260702607126072260732607426075260762607726078260792608026081260822608326084260852608626087260882608926090260912609226093260942609526096260972609826099261002610126102261032610426105261062610726108261092611026111261122611326114261152611626117261182611926120261212612226123261242612526126261272612826129261302613126132261332613426135261362613726138261392614026141261422614326144261452614626147261482614926150261512615226153261542615526156261572615826159261602616126162261632616426165261662616726168261692617026171261722617326174261752617626177261782617926180261812618226183261842618526186261872618826189261902619126192261932619426195261962619726198261992620026201262022620326204262052620626207262082620926210262112621226213262142621526216262172621826219262202622126222262232622426225262262622726228262292623026231262322623326234262352623626237262382623926240262412624226243262442624526246262472624826249262502625126252262532625426255262562625726258262592626026261262622626326264262652626626267262682626926270262712627226273262742627526276262772627826279262802628126282262832628426285262862628726288262892629026291262922629326294262952629626297262982629926300263012630226303263042630526306263072630826309263102631126312263132631426315263162631726318263192632026321263222632326324263252632626327263282632926330263312633226333263342633526336263372633826339263402634126342263432634426345263462634726348263492635026351263522635326354263552635626357263582635926360263612636226363263642636526366263672636826369263702637126372263732637426375263762637726378263792638026381263822638326384263852638626387263882638926390263912639226393263942639526396263972639826399264002640126402264032640426405264062640726408264092641026411264122641326414264152641626417264182641926420264212642226423264242642526426264272642826429264302643126432264332643426435264362643726438264392644026441264422644326444264452644626447264482644926450264512645226453264542645526456264572645826459264602646126462264632646426465264662646726468264692647026471264722647326474264752647626477264782647926480264812648226483264842648526486264872648826489264902649126492264932649426495264962649726498264992650026501265022650326504265052650626507265082650926510265112651226513265142651526516265172651826519265202652126522265232652426525265262652726528265292653026531265322653326534265352653626537265382653926540265412654226543265442654526546265472654826549265502655126552265532655426555265562655726558265592656026561265622656326564265652656626567265682656926570265712657226573265742657526576265772657826579265802658126582265832658426585265862658726588265892659026591265922659326594265952659626597265982659926600266012660226603266042660526606266072660826609266102661126612266132661426615266162661726618266192662026621266222662326624266252662626627266282662926630266312663226633266342663526636266372663826639266402664126642266432664426645266462664726648266492665026651266522665326654266552665626657266582665926660266612666226663266642666526666266672666826669266702667126672266732667426675266762667726678266792668026681266822668326684266852668626687266882668926690266912669226693266942669526696266972669826699267002670126702267032670426705267062670726708267092671026711267122671326714267152671626717267182671926720267212672226723267242672526726267272672826729267302673126732267332673426735267362673726738267392674026741267422674326744267452674626747267482674926750267512675226753267542675526756267572675826759267602676126762267632676426765267662676726768267692677026771267722677326774267752677626777267782677926780267812678226783267842678526786267872678826789267902679126792267932679426795267962679726798267992680026801268022680326804268052680626807268082680926810268112681226813268142681526816268172681826819268202682126822268232682426825268262682726828268292683026831268322683326834268352683626837268382683926840268412684226843268442684526846268472684826849268502685126852268532685426855268562685726858268592686026861268622686326864268652686626867268682686926870268712687226873268742687526876268772687826879268802688126882268832688426885268862688726888268892689026891268922689326894268952689626897268982689926900269012690226903269042690526906269072690826909269102691126912269132691426915269162691726918269192692026921269222692326924269252692626927269282692926930269312693226933269342693526936269372693826939269402694126942269432694426945269462694726948269492695026951269522695326954269552695626957269582695926960269612696226963269642696526966269672696826969269702697126972269732697426975269762697726978269792698026981269822698326984269852698626987269882698926990269912699226993269942699526996269972699826999270002700127002270032700427005270062700727008270092701027011270122701327014270152701627017270182701927020270212702227023270242702527026270272702827029270302703127032270332703427035270362703727038270392704027041270422704327044270452704627047270482704927050270512705227053270542705527056270572705827059270602706127062270632706427065270662706727068270692707027071270722707327074270752707627077270782707927080270812708227083270842708527086270872708827089270902709127092270932709427095270962709727098270992710027101271022710327104271052710627107271082710927110271112711227113271142711527116271172711827119271202712127122271232712427125271262712727128271292713027131271322713327134271352713627137271382713927140271412714227143271442714527146271472714827149271502715127152271532715427155271562715727158271592716027161271622716327164271652716627167271682716927170271712717227173271742717527176271772717827179271802718127182271832718427185271862718727188271892719027191271922719327194271952719627197271982719927200272012720227203272042720527206272072720827209272102721127212272132721427215272162721727218272192722027221272222722327224272252722627227272282722927230272312723227233272342723527236272372723827239272402724127242272432724427245272462724727248272492725027251272522725327254272552725627257272582725927260272612726227263272642726527266272672726827269272702727127272272732727427275272762727727278272792728027281272822728327284272852728627287272882728927290272912729227293272942729527296272972729827299273002730127302273032730427305273062730727308273092731027311273122731327314273152731627317273182731927320273212732227323273242732527326273272732827329273302733127332273332733427335273362733727338273392734027341273422734327344273452734627347273482734927350273512735227353273542735527356273572735827359273602736127362273632736427365273662736727368273692737027371273722737327374273752737627377273782737927380273812738227383273842738527386273872738827389273902739127392273932739427395273962739727398273992740027401274022740327404274052740627407274082740927410274112741227413274142741527416274172741827419274202742127422274232742427425274262742727428274292743027431274322743327434274352743627437274382743927440274412744227443274442744527446274472744827449274502745127452274532745427455274562745727458274592746027461274622746327464274652746627467274682746927470274712747227473274742747527476274772747827479274802748127482274832748427485274862748727488274892749027491274922749327494274952749627497274982749927500275012750227503275042750527506275072750827509275102751127512275132751427515275162751727518275192752027521275222752327524275252752627527275282752927530275312753227533275342753527536275372753827539275402754127542275432754427545275462754727548275492755027551275522755327554275552755627557275582755927560275612756227563275642756527566275672756827569275702757127572275732757427575275762757727578275792758027581275822758327584275852758627587275882758927590275912759227593275942759527596275972759827599276002760127602276032760427605276062760727608276092761027611276122761327614276152761627617276182761927620276212762227623276242762527626276272762827629276302763127632276332763427635276362763727638276392764027641276422764327644276452764627647276482764927650276512765227653276542765527656276572765827659276602766127662276632766427665276662766727668276692767027671276722767327674276752767627677276782767927680276812768227683276842768527686276872768827689276902769127692276932769427695276962769727698276992770027701277022770327704277052770627707277082770927710277112771227713277142771527716277172771827719277202772127722277232772427725277262772727728277292773027731277322773327734277352773627737277382773927740277412774227743277442774527746277472774827749277502775127752277532775427755277562775727758277592776027761277622776327764277652776627767277682776927770277712777227773277742777527776277772777827779277802778127782277832778427785277862778727788277892779027791277922779327794277952779627797277982779927800278012780227803278042780527806278072780827809278102781127812278132781427815278162781727818278192782027821278222782327824278252782627827278282782927830278312783227833278342783527836278372783827839278402784127842278432784427845278462784727848278492785027851278522785327854278552785627857278582785927860278612786227863278642786527866278672786827869278702787127872278732787427875278762787727878278792788027881278822788327884278852788627887278882788927890278912789227893278942789527896278972789827899279002790127902279032790427905279062790727908279092791027911279122791327914279152791627917279182791927920279212792227923279242792527926279272792827929279302793127932279332793427935279362793727938279392794027941279422794327944279452794627947279482794927950279512795227953279542795527956279572795827959279602796127962279632796427965279662796727968279692797027971279722797327974279752797627977279782797927980279812798227983279842798527986279872798827989279902799127992279932799427995279962799727998279992800028001280022800328004280052800628007280082800928010280112801228013280142801528016280172801828019280202802128022280232802428025280262802728028280292803028031280322803328034280352803628037280382803928040280412804228043280442804528046280472804828049280502805128052280532805428055280562805728058280592806028061280622806328064280652806628067280682806928070280712807228073280742807528076280772807828079280802808128082280832808428085280862808728088280892809028091280922809328094280952809628097280982809928100281012810228103281042810528106281072810828109281102811128112281132811428115281162811728118281192812028121281222812328124281252812628127281282812928130281312813228133281342813528136281372813828139281402814128142281432814428145281462814728148281492815028151281522815328154281552815628157281582815928160281612816228163281642816528166281672816828169281702817128172281732817428175281762817728178281792818028181281822818328184281852818628187281882818928190281912819228193281942819528196281972819828199282002820128202282032820428205282062820728208282092821028211282122821328214282152821628217282182821928220282212822228223282242822528226282272822828229282302823128232282332823428235282362823728238282392824028241282422824328244282452824628247282482824928250282512825228253282542825528256282572825828259282602826128262282632826428265282662826728268282692827028271282722827328274282752827628277282782827928280282812828228283282842828528286282872828828289282902829128292282932829428295282962829728298282992830028301283022830328304283052830628307283082830928310283112831228313283142831528316283172831828319283202832128322283232832428325283262832728328283292833028331283322833328334283352833628337283382833928340283412834228343283442834528346283472834828349283502835128352283532835428355283562835728358283592836028361283622836328364283652836628367283682836928370283712837228373283742837528376283772837828379283802838128382283832838428385283862838728388283892839028391283922839328394283952839628397283982839928400284012840228403284042840528406284072840828409284102841128412284132841428415284162841728418284192842028421284222842328424284252842628427284282842928430284312843228433284342843528436284372843828439284402844128442284432844428445284462844728448284492845028451284522845328454284552845628457284582845928460284612846228463284642846528466284672846828469284702847128472284732847428475284762847728478284792848028481284822848328484284852848628487284882848928490284912849228493284942849528496284972849828499285002850128502285032850428505285062850728508285092851028511285122851328514285152851628517285182851928520285212852228523285242852528526285272852828529285302853128532285332853428535285362853728538285392854028541285422854328544285452854628547285482854928550285512855228553285542855528556285572855828559285602856128562285632856428565285662856728568285692857028571285722857328574285752857628577285782857928580285812858228583285842858528586285872858828589285902859128592285932859428595285962859728598285992860028601286022860328604286052860628607286082860928610286112861228613286142861528616286172861828619286202862128622286232862428625286262862728628286292863028631286322863328634286352863628637286382863928640286412864228643286442864528646286472864828649286502865128652286532865428655286562865728658286592866028661286622866328664286652866628667286682866928670286712867228673286742867528676286772867828679286802868128682286832868428685286862868728688286892869028691286922869328694286952869628697286982869928700287012870228703287042870528706287072870828709287102871128712287132871428715287162871728718287192872028721287222872328724287252872628727287282872928730287312873228733287342873528736287372873828739287402874128742287432874428745287462874728748287492875028751287522875328754287552875628757287582875928760287612876228763287642876528766287672876828769287702877128772287732877428775287762877728778287792878028781287822878328784287852878628787287882878928790287912879228793287942879528796287972879828799288002880128802288032880428805288062880728808288092881028811288122881328814288152881628817288182881928820288212882228823288242882528826288272882828829288302883128832288332883428835288362883728838288392884028841288422884328844288452884628847288482884928850288512885228853288542885528856288572885828859288602886128862288632886428865288662886728868288692887028871288722887328874288752887628877288782887928880288812888228883288842888528886288872888828889288902889128892288932889428895288962889728898288992890028901289022890328904289052890628907289082890928910289112891228913289142891528916289172891828919289202892128922289232892428925289262892728928289292893028931289322893328934289352893628937289382893928940289412894228943289442894528946289472894828949289502895128952289532895428955289562895728958289592896028961289622896328964289652896628967289682896928970289712897228973289742897528976289772897828979289802898128982289832898428985289862898728988289892899028991289922899328994289952899628997289982899929000290012900229003290042900529006290072900829009290102901129012290132901429015290162901729018290192902029021290222902329024290252902629027290282902929030290312903229033290342903529036290372903829039290402904129042290432904429045290462904729048290492905029051290522905329054290552905629057290582905929060290612906229063290642906529066290672906829069290702907129072290732907429075290762907729078290792908029081290822908329084290852908629087290882908929090290912909229093290942909529096290972909829099291002910129102291032910429105291062910729108291092911029111291122911329114291152911629117291182911929120291212912229123291242912529126291272912829129291302913129132291332913429135291362913729138291392914029141291422914329144291452914629147291482914929150291512915229153291542915529156291572915829159291602916129162291632916429165291662916729168291692917029171291722917329174291752917629177291782917929180291812918229183291842918529186291872918829189291902919129192291932919429195291962919729198291992920029201292022920329204292052920629207292082920929210292112921229213292142921529216292172921829219292202922129222292232922429225292262922729228292292923029231292322923329234292352923629237292382923929240292412924229243292442924529246292472924829249292502925129252292532925429255292562925729258292592926029261292622926329264292652926629267292682926929270292712927229273292742927529276292772927829279292802928129282292832928429285292862928729288292892929029291292922929329294292952929629297292982929929300293012930229303293042930529306293072930829309293102931129312293132931429315293162931729318293192932029321293222932329324293252932629327293282932929330293312933229333293342933529336293372933829339293402934129342293432934429345293462934729348293492935029351293522935329354293552935629357293582935929360293612936229363293642936529366293672936829369293702937129372293732937429375293762937729378293792938029381293822938329384293852938629387293882938929390293912939229393293942939529396293972939829399294002940129402294032940429405294062940729408294092941029411294122941329414294152941629417294182941929420294212942229423294242942529426294272942829429294302943129432294332943429435294362943729438294392944029441294422944329444294452944629447294482944929450294512945229453294542945529456294572945829459294602946129462294632946429465294662946729468294692947029471294722947329474294752947629477294782947929480294812948229483294842948529486294872948829489294902949129492294932949429495294962949729498294992950029501295022950329504295052950629507295082950929510295112951229513295142951529516295172951829519295202952129522295232952429525295262952729528295292953029531295322953329534295352953629537295382953929540295412954229543295442954529546295472954829549295502955129552295532955429555295562955729558295592956029561295622956329564295652956629567295682956929570295712957229573295742957529576295772957829579295802958129582295832958429585295862958729588295892959029591295922959329594295952959629597295982959929600296012960229603296042960529606296072960829609296102961129612296132961429615296162961729618296192962029621296222962329624296252962629627296282962929630296312963229633296342963529636296372963829639296402964129642296432964429645296462964729648296492965029651296522965329654296552965629657296582965929660296612966229663296642966529666296672966829669296702967129672296732967429675296762967729678296792968029681296822968329684296852968629687296882968929690296912969229693296942969529696296972969829699297002970129702297032970429705297062970729708297092971029711297122971329714297152971629717297182971929720297212972229723297242972529726297272972829729297302973129732297332973429735297362973729738297392974029741297422974329744297452974629747297482974929750297512975229753297542975529756297572975829759297602976129762297632976429765297662976729768297692977029771297722977329774297752977629777297782977929780297812978229783297842978529786297872978829789297902979129792297932979429795297962979729798297992980029801298022980329804298052980629807298082980929810298112981229813298142981529816298172981829819298202982129822298232982429825298262982729828298292983029831298322983329834298352983629837298382983929840298412984229843298442984529846298472984829849298502985129852298532985429855298562985729858298592986029861298622986329864298652986629867298682986929870298712987229873298742987529876298772987829879298802988129882298832988429885298862988729888298892989029891298922989329894298952989629897298982989929900299012990229903299042990529906299072990829909299102991129912299132991429915299162991729918299192992029921299222992329924299252992629927299282992929930299312993229933299342993529936299372993829939299402994129942299432994429945299462994729948299492995029951299522995329954299552995629957299582995929960299612996229963299642996529966299672996829969299702997129972299732997429975299762997729978299792998029981299822998329984299852998629987299882998929990299912999229993299942999529996299972999829999300003000130002300033000430005300063000730008300093001030011300123001330014300153001630017300183001930020300213002230023300243002530026300273002830029300303003130032300333003430035300363003730038300393004030041300423004330044300453004630047300483004930050300513005230053300543005530056300573005830059300603006130062300633006430065300663006730068300693007030071300723007330074300753007630077300783007930080300813008230083300843008530086300873008830089300903009130092300933009430095300963009730098300993010030101301023010330104301053010630107301083010930110301113011230113301143011530116301173011830119301203012130122301233012430125301263012730128301293013030131301323013330134301353013630137301383013930140301413014230143301443014530146301473014830149301503015130152301533015430155301563015730158301593016030161301623016330164301653016630167301683016930170301713017230173301743017530176301773017830179301803018130182301833018430185301863018730188301893019030191301923019330194301953019630197301983019930200302013020230203302043020530206302073020830209302103021130212302133021430215302163021730218302193022030221302223022330224302253022630227302283022930230302313023230233302343023530236302373023830239302403024130242302433024430245302463024730248302493025030251302523025330254302553025630257302583025930260302613026230263302643026530266302673026830269302703027130272302733027430275302763027730278302793028030281302823028330284302853028630287302883028930290302913029230293302943029530296302973029830299303003030130302303033030430305303063030730308303093031030311303123031330314303153031630317303183031930320303213032230323303243032530326303273032830329303303033130332303333033430335303363033730338303393034030341303423034330344303453034630347303483034930350303513035230353303543035530356303573035830359303603036130362303633036430365303663036730368303693037030371303723037330374303753037630377303783037930380303813038230383303843038530386303873038830389303903039130392303933039430395303963039730398303993040030401304023040330404304053040630407304083040930410304113041230413304143041530416304173041830419304203042130422304233042430425304263042730428304293043030431304323043330434304353043630437304383043930440304413044230443304443044530446304473044830449304503045130452304533045430455304563045730458304593046030461304623046330464304653046630467304683046930470304713047230473304743047530476304773047830479304803048130482304833048430485304863048730488304893049030491304923049330494304953049630497304983049930500305013050230503305043050530506305073050830509305103051130512305133051430515305163051730518305193052030521305223052330524305253052630527305283052930530305313053230533305343053530536305373053830539305403054130542305433054430545305463054730548305493055030551305523055330554305553055630557305583055930560305613056230563305643056530566305673056830569305703057130572305733057430575305763057730578305793058030581305823058330584305853058630587305883058930590305913059230593305943059530596305973059830599306003060130602306033060430605306063060730608306093061030611306123061330614306153061630617306183061930620306213062230623306243062530626306273062830629306303063130632306333063430635306363063730638306393064030641306423064330644306453064630647306483064930650306513065230653306543065530656306573065830659306603066130662306633066430665306663066730668306693067030671306723067330674306753067630677306783067930680306813068230683306843068530686306873068830689306903069130692306933069430695306963069730698306993070030701307023070330704307053070630707307083070930710307113071230713307143071530716307173071830719307203072130722307233072430725307263072730728307293073030731307323073330734307353073630737307383073930740307413074230743307443074530746307473074830749307503075130752307533075430755307563075730758307593076030761307623076330764307653076630767307683076930770307713077230773307743077530776307773077830779307803078130782307833078430785307863078730788307893079030791307923079330794307953079630797307983079930800308013080230803308043080530806308073080830809308103081130812308133081430815308163081730818308193082030821308223082330824308253082630827308283082930830308313083230833308343083530836308373083830839308403084130842308433084430845308463084730848308493085030851308523085330854308553085630857308583085930860308613086230863308643086530866308673086830869308703087130872308733087430875308763087730878308793088030881308823088330884308853088630887308883088930890308913089230893308943089530896308973089830899309003090130902309033090430905309063090730908309093091030911309123091330914309153091630917309183091930920309213092230923309243092530926309273092830929309303093130932309333093430935309363093730938309393094030941309423094330944309453094630947309483094930950309513095230953309543095530956309573095830959309603096130962309633096430965309663096730968309693097030971309723097330974309753097630977309783097930980309813098230983309843098530986309873098830989309903099130992309933099430995309963099730998309993100031001310023100331004310053100631007310083100931010310113101231013310143101531016310173101831019310203102131022310233102431025310263102731028310293103031031310323103331034310353103631037310383103931040310413104231043310443104531046310473104831049310503105131052310533105431055310563105731058310593106031061310623106331064310653106631067310683106931070310713107231073310743107531076310773107831079310803108131082310833108431085310863108731088310893109031091310923109331094310953109631097310983109931100311013110231103311043110531106311073110831109311103111131112311133111431115311163111731118311193112031121311223112331124311253112631127311283112931130311313113231133311343113531136311373113831139311403114131142311433114431145311463114731148311493115031151311523115331154311553115631157311583115931160311613116231163311643116531166311673116831169311703117131172311733117431175311763117731178311793118031181311823118331184311853118631187311883118931190311913119231193311943119531196311973119831199312003120131202312033120431205312063120731208312093121031211312123121331214312153121631217312183121931220312213122231223312243122531226312273122831229312303123131232312333123431235312363123731238312393124031241312423124331244312453124631247312483124931250312513125231253312543125531256312573125831259312603126131262312633126431265312663126731268312693127031271312723127331274312753127631277312783127931280312813128231283312843128531286312873128831289312903129131292312933129431295312963129731298312993130031301313023130331304313053130631307313083130931310313113131231313313143131531316313173131831319313203132131322313233132431325313263132731328313293133031331313323133331334313353133631337313383133931340313413134231343313443134531346313473134831349313503135131352313533135431355313563135731358313593136031361313623136331364313653136631367313683136931370313713137231373313743137531376313773137831379313803138131382313833138431385313863138731388313893139031391313923139331394313953139631397313983139931400314013140231403314043140531406314073140831409314103141131412314133141431415314163141731418314193142031421314223142331424314253142631427314283142931430314313143231433314343143531436314373143831439314403144131442314433144431445314463144731448314493145031451314523145331454314553145631457314583145931460314613146231463314643146531466314673146831469314703147131472314733147431475314763147731478314793148031481314823148331484314853148631487314883148931490314913149231493314943149531496314973149831499315003150131502315033150431505315063150731508315093151031511315123151331514315153151631517315183151931520315213152231523315243152531526315273152831529315303153131532315333153431535315363153731538315393154031541315423154331544315453154631547315483154931550315513155231553315543155531556315573155831559315603156131562315633156431565315663156731568315693157031571315723157331574315753157631577315783157931580315813158231583315843158531586315873158831589315903159131592315933159431595315963159731598315993160031601316023160331604316053160631607316083160931610316113161231613316143161531616316173161831619316203162131622316233162431625316263162731628316293163031631316323163331634316353163631637316383163931640316413164231643316443164531646316473164831649316503165131652316533165431655316563165731658316593166031661316623166331664316653166631667316683166931670316713167231673316743167531676316773167831679316803168131682316833168431685316863168731688316893169031691316923169331694316953169631697316983169931700317013170231703317043170531706317073170831709317103171131712317133171431715317163171731718317193172031721317223172331724317253172631727317283172931730317313173231733317343173531736317373173831739317403174131742317433174431745317463174731748317493175031751317523175331754317553175631757317583175931760317613176231763317643176531766317673176831769317703177131772317733177431775317763177731778317793178031781317823178331784317853178631787317883178931790317913179231793317943179531796317973179831799318003180131802318033180431805318063180731808318093181031811318123181331814318153181631817318183181931820318213182231823318243182531826318273182831829318303183131832318333183431835318363183731838318393184031841318423184331844318453184631847318483184931850318513185231853318543185531856318573185831859318603186131862318633186431865318663186731868318693187031871318723187331874318753187631877318783187931880318813188231883318843188531886318873188831889318903189131892318933189431895318963189731898318993190031901319023190331904319053190631907319083190931910319113191231913319143191531916319173191831919319203192131922319233192431925319263192731928319293193031931319323193331934319353193631937319383193931940319413194231943319443194531946319473194831949319503195131952319533195431955319563195731958319593196031961319623196331964319653196631967319683196931970319713197231973319743197531976319773197831979319803198131982319833198431985319863198731988319893199031991319923199331994319953199631997319983199932000320013200232003320043200532006320073200832009320103201132012320133201432015320163201732018320193202032021320223202332024320253202632027320283202932030320313203232033320343203532036320373203832039320403204132042320433204432045320463204732048320493205032051320523205332054320553205632057320583205932060320613206232063320643206532066320673206832069320703207132072320733207432075320763207732078320793208032081320823208332084320853208632087320883208932090320913209232093320943209532096320973209832099321003210132102321033210432105321063210732108321093211032111321123211332114321153211632117321183211932120321213212232123321243212532126321273212832129321303213132132321333213432135321363213732138321393214032141321423214332144321453214632147321483214932150321513215232153321543215532156321573215832159321603216132162321633216432165321663216732168321693217032171321723217332174321753217632177321783217932180321813218232183321843218532186321873218832189321903219132192321933219432195321963219732198321993220032201322023220332204322053220632207322083220932210322113221232213322143221532216322173221832219322203222132222322233222432225322263222732228322293223032231322323223332234322353223632237322383223932240322413224232243322443224532246322473224832249322503225132252322533225432255322563225732258322593226032261322623226332264322653226632267322683226932270322713227232273322743227532276322773227832279322803228132282322833228432285322863228732288322893229032291322923229332294322953229632297322983229932300323013230232303323043230532306323073230832309323103231132312323133231432315323163231732318323193232032321323223232332324323253232632327323283232932330323313233232333323343233532336323373233832339323403234132342323433234432345323463234732348323493235032351323523235332354323553235632357323583235932360323613236232363323643236532366323673236832369323703237132372323733237432375323763237732378323793238032381323823238332384323853238632387323883238932390323913239232393323943239532396323973239832399324003240132402324033240432405324063240732408324093241032411324123241332414324153241632417324183241932420324213242232423324243242532426324273242832429324303243132432324333243432435324363243732438324393244032441324423244332444324453244632447324483244932450324513245232453324543245532456324573245832459324603246132462324633246432465324663246732468324693247032471324723247332474324753247632477324783247932480324813248232483324843248532486324873248832489324903249132492324933249432495324963249732498324993250032501325023250332504325053250632507325083250932510325113251232513325143251532516325173251832519325203252132522325233252432525325263252732528325293253032531325323253332534325353253632537325383253932540325413254232543325443254532546325473254832549325503255132552325533255432555325563255732558325593256032561325623256332564325653256632567325683256932570325713257232573325743257532576325773257832579325803258132582325833258432585325863258732588325893259032591325923259332594325953259632597325983259932600326013260232603326043260532606326073260832609326103261132612326133261432615326163261732618326193262032621326223262332624326253262632627326283262932630326313263232633326343263532636326373263832639326403264132642326433264432645326463264732648326493265032651326523265332654326553265632657326583265932660326613266232663326643266532666326673266832669326703267132672326733267432675326763267732678326793268032681326823268332684326853268632687326883268932690326913269232693326943269532696326973269832699327003270132702327033270432705327063270732708327093271032711327123271332714327153271632717327183271932720327213272232723327243272532726327273272832729327303273132732327333273432735327363273732738327393274032741327423274332744327453274632747327483274932750327513275232753327543275532756327573275832759327603276132762327633276432765327663276732768327693277032771327723277332774327753277632777327783277932780327813278232783327843278532786327873278832789327903279132792327933279432795327963279732798327993280032801328023280332804328053280632807328083280932810328113281232813328143281532816328173281832819328203282132822328233282432825328263282732828328293283032831328323283332834328353283632837328383283932840328413284232843328443284532846328473284832849328503285132852328533285432855328563285732858328593286032861328623286332864328653286632867328683286932870328713287232873328743287532876328773287832879328803288132882328833288432885328863288732888328893289032891328923289332894328953289632897328983289932900329013290232903329043290532906329073290832909329103291132912329133291432915329163291732918329193292032921329223292332924329253292632927329283292932930329313293232933329343293532936329373293832939329403294132942329433294432945329463294732948329493295032951329523295332954329553295632957329583295932960329613296232963329643296532966329673296832969329703297132972329733297432975329763297732978329793298032981329823298332984329853298632987329883298932990329913299232993329943299532996329973299832999330003300133002330033300433005330063300733008330093301033011330123301333014330153301633017330183301933020330213302233023330243302533026330273302833029330303303133032330333303433035330363303733038330393304033041330423304333044330453304633047330483304933050330513305233053330543305533056330573305833059330603306133062330633306433065330663306733068330693307033071330723307333074330753307633077330783307933080330813308233083330843308533086330873308833089330903309133092330933309433095330963309733098330993310033101331023310333104331053310633107331083310933110331113311233113331143311533116331173311833119331203312133122331233312433125331263312733128331293313033131331323313333134331353313633137331383313933140331413314233143331443314533146331473314833149331503315133152331533315433155331563315733158331593316033161331623316333164331653316633167331683316933170331713317233173331743317533176331773317833179331803318133182331833318433185331863318733188331893319033191331923319333194331953319633197331983319933200332013320233203332043320533206332073320833209332103321133212332133321433215332163321733218332193322033221332223322333224332253322633227332283322933230332313323233233332343323533236332373323833239332403324133242332433324433245332463324733248332493325033251332523325333254332553325633257332583325933260332613326233263332643326533266332673326833269332703327133272332733327433275332763327733278332793328033281332823328333284332853328633287332883328933290332913329233293332943329533296332973329833299333003330133302333033330433305333063330733308333093331033311333123331333314333153331633317333183331933320333213332233323333243332533326333273332833329333303333133332333333333433335333363333733338333393334033341333423334333344333453334633347333483334933350333513335233353333543335533356333573335833359333603336133362333633336433365333663336733368333693337033371333723337333374333753337633377333783337933380333813338233383333843338533386333873338833389333903339133392333933339433395333963339733398333993340033401334023340333404334053340633407334083340933410334113341233413334143341533416334173341833419334203342133422334233342433425334263342733428334293343033431334323343333434334353343633437334383343933440334413344233443334443344533446334473344833449334503345133452334533345433455334563345733458334593346033461334623346333464334653346633467334683346933470334713347233473334743347533476334773347833479334803348133482334833348433485334863348733488334893349033491334923349333494334953349633497334983349933500335013350233503335043350533506335073350833509335103351133512335133351433515335163351733518335193352033521335223352333524335253352633527335283352933530335313353233533335343353533536335373353833539335403354133542335433354433545335463354733548335493355033551335523355333554335553355633557335583355933560335613356233563335643356533566335673356833569335703357133572335733357433575335763357733578335793358033581335823358333584335853358633587335883358933590335913359233593335943359533596335973359833599336003360133602336033360433605336063360733608336093361033611336123361333614336153361633617336183361933620336213362233623336243362533626336273362833629336303363133632336333363433635336363363733638336393364033641336423364333644336453364633647336483364933650336513365233653336543365533656336573365833659336603366133662336633366433665336663366733668336693367033671336723367333674336753367633677336783367933680336813368233683336843368533686336873368833689336903369133692336933369433695336963369733698336993370033701337023370333704337053370633707337083370933710337113371233713337143371533716337173371833719337203372133722337233372433725337263372733728337293373033731337323373333734337353373633737337383373933740337413374233743337443374533746337473374833749337503375133752337533375433755337563375733758337593376033761337623376333764337653376633767337683376933770337713377233773337743377533776337773377833779337803378133782337833378433785337863378733788337893379033791337923379333794337953379633797337983379933800338013380233803338043380533806338073380833809338103381133812338133381433815338163381733818338193382033821338223382333824338253382633827338283382933830338313383233833338343383533836338373383833839338403384133842338433384433845338463384733848338493385033851338523385333854338553385633857338583385933860338613386233863338643386533866338673386833869338703387133872338733387433875338763387733878338793388033881338823388333884338853388633887338883388933890338913389233893338943389533896338973389833899339003390133902339033390433905339063390733908339093391033911339123391333914339153391633917339183391933920339213392233923339243392533926339273392833929339303393133932339333393433935339363393733938339393394033941339423394333944339453394633947339483394933950339513395233953339543395533956339573395833959339603396133962339633396433965339663396733968339693397033971339723397333974339753397633977339783397933980339813398233983339843398533986339873398833989339903399133992339933399433995339963399733998339993400034001340023400334004340053400634007340083400934010340113401234013340143401534016340173401834019340203402134022340233402434025340263402734028340293403034031340323403334034340353403634037340383403934040340413404234043340443404534046340473404834049340503405134052340533405434055340563405734058340593406034061340623406334064340653406634067340683406934070340713407234073340743407534076340773407834079340803408134082340833408434085340863408734088340893409034091340923409334094340953409634097340983409934100341013410234103341043410534106341073410834109341103411134112341133411434115341163411734118341193412034121341223412334124341253412634127341283412934130341313413234133341343413534136341373413834139341403414134142341433414434145341463414734148341493415034151341523415334154341553415634157341583415934160341613416234163341643416534166341673416834169341703417134172341733417434175341763417734178341793418034181341823418334184341853418634187341883418934190341913419234193341943419534196341973419834199342003420134202342033420434205342063420734208342093421034211342123421334214342153421634217342183421934220342213422234223342243422534226342273422834229342303423134232342333423434235342363423734238342393424034241342423424334244342453424634247342483424934250342513425234253342543425534256342573425834259342603426134262342633426434265342663426734268342693427034271342723427334274342753427634277342783427934280342813428234283342843428534286342873428834289342903429134292342933429434295342963429734298342993430034301343023430334304343053430634307343083430934310343113431234313343143431534316343173431834319343203432134322343233432434325343263432734328343293433034331343323433334334343353433634337343383433934340343413434234343343443434534346343473434834349343503435134352343533435434355343563435734358343593436034361343623436334364343653436634367343683436934370343713437234373343743437534376343773437834379343803438134382343833438434385343863438734388343893439034391343923439334394343953439634397343983439934400344013440234403344043440534406344073440834409344103441134412344133441434415344163441734418344193442034421344223442334424344253442634427344283442934430344313443234433344343443534436344373443834439344403444134442344433444434445344463444734448344493445034451344523445334454344553445634457344583445934460344613446234463344643446534466344673446834469344703447134472344733447434475344763447734478344793448034481344823448334484344853448634487344883448934490344913449234493344943449534496344973449834499345003450134502345033450434505345063450734508345093451034511345123451334514345153451634517345183451934520345213452234523345243452534526345273452834529345303453134532345333453434535345363453734538345393454034541345423454334544345453454634547345483454934550345513455234553345543455534556345573455834559345603456134562345633456434565345663456734568345693457034571345723457334574345753457634577345783457934580345813458234583345843458534586345873458834589345903459134592345933459434595345963459734598345993460034601346023460334604346053460634607346083460934610346113461234613346143461534616346173461834619346203462134622346233462434625346263462734628346293463034631346323463334634346353463634637346383463934640346413464234643346443464534646346473464834649346503465134652346533465434655346563465734658346593466034661346623466334664346653466634667346683466934670346713467234673346743467534676346773467834679346803468134682346833468434685346863468734688346893469034691346923469334694346953469634697346983469934700347013470234703347043470534706347073470834709347103471134712347133471434715347163471734718347193472034721347223472334724347253472634727347283472934730347313473234733347343473534736347373473834739347403474134742347433474434745347463474734748347493475034751347523475334754347553475634757347583475934760347613476234763347643476534766347673476834769347703477134772347733477434775347763477734778347793478034781347823478334784347853478634787347883478934790347913479234793347943479534796347973479834799348003480134802348033480434805348063480734808348093481034811348123481334814348153481634817348183481934820348213482234823348243482534826348273482834829348303483134832348333483434835348363483734838348393484034841348423484334844348453484634847348483484934850348513485234853348543485534856348573485834859348603486134862348633486434865348663486734868348693487034871348723487334874348753487634877348783487934880348813488234883348843488534886348873488834889348903489134892348933489434895348963489734898348993490034901349023490334904349053490634907349083490934910349113491234913349143491534916349173491834919349203492134922349233492434925349263492734928349293493034931349323493334934349353493634937349383493934940349413494234943349443494534946349473494834949349503495134952349533495434955349563495734958349593496034961349623496334964349653496634967349683496934970349713497234973349743497534976349773497834979349803498134982349833498434985349863498734988349893499034991349923499334994349953499634997349983499935000350013500235003350043500535006350073500835009350103501135012350133501435015350163501735018350193502035021350223502335024350253502635027350283502935030350313503235033350343503535036350373503835039350403504135042350433504435045350463504735048350493505035051350523505335054350553505635057350583505935060350613506235063350643506535066350673506835069350703507135072350733507435075350763507735078350793508035081350823508335084350853508635087350883508935090350913509235093350943509535096350973509835099351003510135102351033510435105351063510735108351093511035111351123511335114351153511635117351183511935120351213512235123351243512535126351273512835129351303513135132351333513435135351363513735138351393514035141351423514335144351453514635147351483514935150351513515235153351543515535156351573515835159351603516135162351633516435165351663516735168351693517035171351723517335174351753517635177351783517935180351813518235183351843518535186351873518835189351903519135192351933519435195351963519735198351993520035201352023520335204352053520635207352083520935210352113521235213352143521535216352173521835219352203522135222352233522435225352263522735228352293523035231352323523335234352353523635237352383523935240352413524235243352443524535246352473524835249352503525135252352533525435255352563525735258352593526035261352623526335264352653526635267352683526935270352713527235273352743527535276352773527835279352803528135282352833528435285352863528735288352893529035291352923529335294352953529635297352983529935300353013530235303353043530535306353073530835309353103531135312353133531435315353163531735318353193532035321353223532335324353253532635327353283532935330353313533235333353343533535336353373533835339353403534135342353433534435345353463534735348353493535035351353523535335354353553535635357353583535935360353613536235363353643536535366353673536835369353703537135372353733537435375353763537735378353793538035381353823538335384353853538635387353883538935390353913539235393353943539535396353973539835399354003540135402354033540435405354063540735408354093541035411354123541335414354153541635417354183541935420354213542235423354243542535426354273542835429354303543135432354333543435435354363543735438354393544035441354423544335444354453544635447354483544935450354513545235453354543545535456354573545835459354603546135462354633546435465354663546735468354693547035471354723547335474354753547635477354783547935480354813548235483354843548535486354873548835489354903549135492354933549435495354963549735498354993550035501355023550335504355053550635507355083550935510355113551235513355143551535516355173551835519355203552135522355233552435525355263552735528355293553035531355323553335534355353553635537355383553935540355413554235543355443554535546355473554835549355503555135552355533555435555355563555735558355593556035561355623556335564355653556635567355683556935570355713557235573355743557535576355773557835579355803558135582355833558435585355863558735588355893559035591355923559335594355953559635597355983559935600356013560235603356043560535606356073560835609356103561135612356133561435615356163561735618356193562035621356223562335624356253562635627356283562935630356313563235633356343563535636356373563835639356403564135642356433564435645356463564735648356493565035651356523565335654356553565635657356583565935660356613566235663356643566535666356673566835669356703567135672356733567435675356763567735678356793568035681356823568335684356853568635687356883568935690356913569235693356943569535696356973569835699357003570135702357033570435705357063570735708357093571035711357123571335714357153571635717357183571935720357213572235723357243572535726357273572835729357303573135732357333573435735357363573735738357393574035741357423574335744357453574635747357483574935750357513575235753357543575535756357573575835759357603576135762357633576435765357663576735768357693577035771357723577335774357753577635777357783577935780357813578235783357843578535786357873578835789357903579135792357933579435795357963579735798357993580035801358023580335804358053580635807358083580935810358113581235813358143581535816358173581835819358203582135822358233582435825358263582735828358293583035831358323583335834358353583635837358383583935840358413584235843358443584535846358473584835849358503585135852358533585435855358563585735858358593586035861358623586335864358653586635867358683586935870358713587235873358743587535876358773587835879358803588135882358833588435885358863588735888358893589035891358923589335894358953589635897358983589935900359013590235903359043590535906359073590835909359103591135912359133591435915359163591735918359193592035921359223592335924359253592635927359283592935930359313593235933359343593535936359373593835939359403594135942359433594435945359463594735948359493595035951359523595335954359553595635957359583595935960359613596235963359643596535966359673596835969359703597135972359733597435975359763597735978359793598035981359823598335984359853598635987359883598935990359913599235993359943599535996359973599835999360003600136002360033600436005360063600736008360093601036011360123601336014360153601636017360183601936020360213602236023360243602536026360273602836029360303603136032360333603436035360363603736038360393604036041360423604336044360453604636047360483604936050360513605236053360543605536056360573605836059360603606136062360633606436065360663606736068360693607036071360723607336074360753607636077360783607936080360813608236083360843608536086360873608836089360903609136092360933609436095360963609736098360993610036101361023610336104361053610636107361083610936110361113611236113361143611536116361173611836119361203612136122361233612436125361263612736128361293613036131361323613336134361353613636137361383613936140361413614236143361443614536146361473614836149361503615136152361533615436155361563615736158361593616036161361623616336164361653616636167361683616936170361713617236173361743617536176361773617836179361803618136182361833618436185361863618736188361893619036191361923619336194361953619636197361983619936200362013620236203362043620536206362073620836209362103621136212362133621436215362163621736218362193622036221362223622336224362253622636227362283622936230362313623236233362343623536236362373623836239362403624136242362433624436245362463624736248362493625036251362523625336254362553625636257362583625936260362613626236263362643626536266362673626836269362703627136272362733627436275362763627736278362793628036281362823628336284362853628636287362883628936290362913629236293362943629536296362973629836299363003630136302363033630436305363063630736308363093631036311363123631336314363153631636317363183631936320363213632236323363243632536326363273632836329363303633136332363333633436335363363633736338363393634036341363423634336344363453634636347363483634936350363513635236353363543635536356363573635836359363603636136362363633636436365363663636736368363693637036371363723637336374363753637636377363783637936380363813638236383363843638536386363873638836389363903639136392363933639436395363963639736398363993640036401364023640336404364053640636407364083640936410364113641236413364143641536416364173641836419364203642136422364233642436425364263642736428364293643036431364323643336434364353643636437364383643936440364413644236443364443644536446364473644836449364503645136452364533645436455364563645736458364593646036461364623646336464364653646636467364683646936470364713647236473364743647536476364773647836479364803648136482364833648436485364863648736488364893649036491364923649336494364953649636497364983649936500365013650236503365043650536506365073650836509365103651136512365133651436515365163651736518365193652036521365223652336524365253652636527365283652936530365313653236533365343653536536365373653836539365403654136542365433654436545365463654736548365493655036551365523655336554365553655636557365583655936560365613656236563365643656536566365673656836569365703657136572365733657436575365763657736578365793658036581365823658336584365853658636587365883658936590365913659236593365943659536596365973659836599366003660136602366033660436605366063660736608366093661036611366123661336614366153661636617366183661936620366213662236623366243662536626366273662836629366303663136632366333663436635366363663736638366393664036641366423664336644366453664636647366483664936650366513665236653366543665536656366573665836659366603666136662366633666436665366663666736668366693667036671366723667336674366753667636677366783667936680366813668236683366843668536686366873668836689366903669136692366933669436695366963669736698366993670036701367023670336704367053670636707367083670936710367113671236713367143671536716367173671836719367203672136722367233672436725367263672736728367293673036731367323673336734367353673636737367383673936740367413674236743367443674536746367473674836749367503675136752367533675436755367563675736758367593676036761367623676336764367653676636767367683676936770367713677236773367743677536776367773677836779367803678136782367833678436785367863678736788367893679036791367923679336794367953679636797367983679936800368013680236803368043680536806368073680836809368103681136812368133681436815368163681736818368193682036821368223682336824368253682636827368283682936830368313683236833368343683536836368373683836839368403684136842368433684436845368463684736848368493685036851368523685336854368553685636857368583685936860368613686236863368643686536866368673686836869368703687136872368733687436875368763687736878368793688036881368823688336884368853688636887368883688936890368913689236893368943689536896368973689836899369003690136902369033690436905369063690736908369093691036911369123691336914369153691636917369183691936920369213692236923369243692536926369273692836929369303693136932369333693436935369363693736938369393694036941369423694336944369453694636947369483694936950369513695236953369543695536956369573695836959369603696136962369633696436965369663696736968369693697036971369723697336974369753697636977369783697936980369813698236983369843698536986369873698836989369903699136992369933699436995369963699736998369993700037001370023700337004370053700637007370083700937010370113701237013370143701537016370173701837019370203702137022370233702437025370263702737028370293703037031370323703337034370353703637037370383703937040370413704237043370443704537046370473704837049370503705137052370533705437055370563705737058370593706037061370623706337064370653706637067370683706937070370713707237073370743707537076370773707837079370803708137082370833708437085370863708737088370893709037091370923709337094370953709637097370983709937100371013710237103371043710537106371073710837109371103711137112371133711437115371163711737118371193712037121371223712337124371253712637127371283712937130371313713237133371343713537136371373713837139371403714137142371433714437145371463714737148371493715037151371523715337154371553715637157371583715937160371613716237163371643716537166371673716837169371703717137172371733717437175371763717737178371793718037181371823718337184371853718637187371883718937190371913719237193371943719537196371973719837199372003720137202372033720437205372063720737208372093721037211372123721337214372153721637217372183721937220372213722237223372243722537226372273722837229372303723137232372333723437235372363723737238372393724037241372423724337244372453724637247372483724937250372513725237253372543725537256372573725837259372603726137262372633726437265372663726737268372693727037271372723727337274372753727637277372783727937280372813728237283372843728537286372873728837289372903729137292372933729437295372963729737298372993730037301373023730337304373053730637307373083730937310373113731237313373143731537316373173731837319373203732137322373233732437325373263732737328373293733037331373323733337334373353733637337373383733937340373413734237343373443734537346373473734837349373503735137352373533735437355373563735737358373593736037361373623736337364373653736637367373683736937370373713737237373373743737537376373773737837379373803738137382373833738437385373863738737388373893739037391373923739337394373953739637397373983739937400374013740237403374043740537406374073740837409374103741137412374133741437415374163741737418374193742037421374223742337424374253742637427374283742937430374313743237433374343743537436374373743837439374403744137442374433744437445374463744737448374493745037451374523745337454374553745637457374583745937460374613746237463374643746537466374673746837469374703747137472374733747437475374763747737478374793748037481374823748337484374853748637487374883748937490374913749237493374943749537496374973749837499375003750137502375033750437505375063750737508375093751037511375123751337514375153751637517375183751937520375213752237523375243752537526375273752837529375303753137532375333753437535375363753737538375393754037541375423754337544375453754637547375483754937550375513755237553375543755537556375573755837559375603756137562375633756437565375663756737568375693757037571375723757337574375753757637577375783757937580375813758237583375843758537586375873758837589375903759137592375933759437595375963759737598375993760037601376023760337604376053760637607376083760937610376113761237613376143761537616376173761837619376203762137622376233762437625376263762737628376293763037631376323763337634376353763637637376383763937640376413764237643376443764537646376473764837649376503765137652376533765437655376563765737658376593766037661376623766337664376653766637667376683766937670376713767237673376743767537676376773767837679376803768137682376833768437685376863768737688376893769037691376923769337694376953769637697376983769937700377013770237703377043770537706377073770837709377103771137712377133771437715377163771737718377193772037721377223772337724377253772637727377283772937730377313773237733377343773537736377373773837739377403774137742377433774437745377463774737748377493775037751377523775337754377553775637757377583775937760377613776237763377643776537766377673776837769377703777137772377733777437775377763777737778377793778037781377823778337784377853778637787377883778937790377913779237793377943779537796377973779837799378003780137802378033780437805378063780737808378093781037811378123781337814378153781637817378183781937820378213782237823378243782537826378273782837829378303783137832378333783437835378363783737838378393784037841378423784337844378453784637847378483784937850378513785237853378543785537856378573785837859378603786137862378633786437865378663786737868378693787037871378723787337874378753787637877378783787937880378813788237883378843788537886378873788837889378903789137892378933789437895378963789737898378993790037901379023790337904379053790637907379083790937910379113791237913379143791537916379173791837919379203792137922379233792437925379263792737928379293793037931379323793337934379353793637937379383793937940379413794237943379443794537946379473794837949379503795137952379533795437955379563795737958379593796037961379623796337964379653796637967379683796937970379713797237973379743797537976379773797837979379803798137982379833798437985379863798737988379893799037991379923799337994379953799637997379983799938000380013800238003380043800538006380073800838009380103801138012380133801438015380163801738018380193802038021380223802338024380253802638027380283802938030380313803238033380343803538036380373803838039380403804138042380433804438045380463804738048380493805038051380523805338054380553805638057380583805938060380613806238063380643806538066380673806838069380703807138072380733807438075380763807738078380793808038081380823808338084380853808638087380883808938090380913809238093380943809538096380973809838099381003810138102381033810438105381063810738108381093811038111381123811338114381153811638117381183811938120381213812238123381243812538126381273812838129381303813138132381333813438135381363813738138381393814038141381423814338144381453814638147381483814938150381513815238153381543815538156381573815838159381603816138162381633816438165381663816738168381693817038171381723817338174381753817638177381783817938180381813818238183381843818538186381873818838189381903819138192381933819438195381963819738198381993820038201382023820338204382053820638207382083820938210382113821238213382143821538216382173821838219382203822138222382233822438225382263822738228382293823038231382323823338234382353823638237382383823938240382413824238243382443824538246382473824838249382503825138252382533825438255382563825738258382593826038261382623826338264382653826638267382683826938270382713827238273382743827538276382773827838279382803828138282382833828438285382863828738288382893829038291382923829338294382953829638297382983829938300383013830238303383043830538306383073830838309383103831138312383133831438315383163831738318383193832038321383223832338324383253832638327383283832938330383313833238333383343833538336383373833838339383403834138342383433834438345383463834738348383493835038351383523835338354383553835638357383583835938360383613836238363383643836538366383673836838369383703837138372383733837438375383763837738378383793838038381383823838338384383853838638387383883838938390383913839238393383943839538396383973839838399384003840138402384033840438405384063840738408384093841038411384123841338414384153841638417384183841938420384213842238423384243842538426384273842838429384303843138432384333843438435384363843738438384393844038441384423844338444384453844638447384483844938450384513845238453384543845538456384573845838459384603846138462384633846438465384663846738468384693847038471384723847338474384753847638477384783847938480384813848238483384843848538486384873848838489384903849138492384933849438495384963849738498384993850038501385023850338504385053850638507385083850938510385113851238513385143851538516385173851838519385203852138522385233852438525385263852738528385293853038531385323853338534385353853638537385383853938540385413854238543385443854538546385473854838549385503855138552385533855438555385563855738558385593856038561385623856338564385653856638567385683856938570385713857238573385743857538576385773857838579385803858138582385833858438585385863858738588385893859038591385923859338594385953859638597385983859938600386013860238603386043860538606386073860838609386103861138612386133861438615386163861738618386193862038621386223862338624386253862638627386283862938630386313863238633386343863538636386373863838639386403864138642386433864438645386463864738648386493865038651386523865338654386553865638657386583865938660386613866238663386643866538666386673866838669386703867138672386733867438675386763867738678386793868038681386823868338684386853868638687386883868938690386913869238693386943869538696386973869838699387003870138702387033870438705387063870738708387093871038711387123871338714387153871638717387183871938720387213872238723387243872538726387273872838729387303873138732387333873438735387363873738738387393874038741387423874338744387453874638747387483874938750387513875238753387543875538756387573875838759387603876138762387633876438765387663876738768387693877038771387723877338774387753877638777387783877938780387813878238783387843878538786387873878838789387903879138792387933879438795387963879738798387993880038801388023880338804388053880638807388083880938810388113881238813388143881538816388173881838819388203882138822388233882438825388263882738828388293883038831388323883338834388353883638837388383883938840388413884238843388443884538846388473884838849388503885138852388533885438855388563885738858388593886038861388623886338864388653886638867388683886938870388713887238873388743887538876388773887838879388803888138882388833888438885388863888738888388893889038891388923889338894388953889638897388983889938900389013890238903389043890538906389073890838909389103891138912389133891438915389163891738918389193892038921389223892338924389253892638927389283892938930389313893238933389343893538936389373893838939389403894138942389433894438945389463894738948389493895038951389523895338954389553895638957389583895938960389613896238963389643896538966389673896838969389703897138972389733897438975389763897738978389793898038981389823898338984389853898638987389883898938990389913899238993389943899538996389973899838999390003900139002390033900439005390063900739008390093901039011390123901339014390153901639017390183901939020390213902239023390243902539026390273902839029390303903139032390333903439035390363903739038390393904039041390423904339044390453904639047390483904939050390513905239053390543905539056390573905839059390603906139062390633906439065390663906739068390693907039071390723907339074390753907639077390783907939080390813908239083390843908539086390873908839089390903909139092390933909439095390963909739098390993910039101391023910339104391053910639107391083910939110391113911239113391143911539116391173911839119391203912139122391233912439125391263912739128391293913039131391323913339134391353913639137391383913939140391413914239143391443914539146391473914839149391503915139152391533915439155391563915739158391593916039161391623916339164391653916639167391683916939170391713917239173391743917539176391773917839179391803918139182391833918439185391863918739188391893919039191391923919339194391953919639197391983919939200392013920239203392043920539206392073920839209392103921139212392133921439215392163921739218392193922039221392223922339224392253922639227392283922939230392313923239233392343923539236392373923839239392403924139242392433924439245392463924739248392493925039251392523925339254392553925639257392583925939260392613926239263392643926539266392673926839269392703927139272392733927439275392763927739278392793928039281392823928339284392853928639287392883928939290392913929239293392943929539296392973929839299393003930139302393033930439305393063930739308393093931039311393123931339314393153931639317393183931939320393213932239323393243932539326393273932839329393303933139332393333933439335393363933739338393393934039341393423934339344393453934639347393483934939350393513935239353393543935539356393573935839359393603936139362393633936439365393663936739368393693937039371393723937339374393753937639377393783937939380393813938239383393843938539386393873938839389393903939139392393933939439395393963939739398393993940039401394023940339404394053940639407394083940939410394113941239413394143941539416394173941839419394203942139422394233942439425394263942739428394293943039431394323943339434394353943639437394383943939440394413944239443394443944539446394473944839449394503945139452394533945439455394563945739458394593946039461394623946339464394653946639467394683946939470394713947239473394743947539476394773947839479394803948139482394833948439485394863948739488394893949039491394923949339494394953949639497394983949939500395013950239503395043950539506395073950839509395103951139512395133951439515395163951739518395193952039521395223952339524395253952639527395283952939530395313953239533395343953539536395373953839539395403954139542395433954439545395463954739548395493955039551395523955339554395553955639557395583955939560395613956239563395643956539566395673956839569395703957139572395733957439575395763957739578395793958039581395823958339584395853958639587395883958939590395913959239593395943959539596395973959839599396003960139602396033960439605396063960739608396093961039611396123961339614396153961639617396183961939620396213962239623396243962539626396273962839629396303963139632396333963439635396363963739638396393964039641396423964339644396453964639647396483964939650396513965239653396543965539656396573965839659396603966139662396633966439665396663966739668396693967039671396723967339674396753967639677396783967939680396813968239683396843968539686396873968839689396903969139692396933969439695396963969739698396993970039701397023970339704397053970639707397083970939710397113971239713397143971539716397173971839719397203972139722397233972439725397263972739728397293973039731397323973339734397353973639737397383973939740397413974239743397443974539746397473974839749397503975139752397533975439755397563975739758397593976039761397623976339764397653976639767397683976939770397713977239773397743977539776397773977839779397803978139782397833978439785397863978739788397893979039791397923979339794397953979639797397983979939800398013980239803398043980539806398073980839809398103981139812398133981439815398163981739818398193982039821398223982339824398253982639827398283982939830398313983239833398343983539836398373983839839398403984139842398433984439845398463984739848398493985039851398523985339854398553985639857398583985939860398613986239863398643986539866398673986839869398703987139872398733987439875398763987739878398793988039881398823988339884398853988639887398883988939890398913989239893398943989539896398973989839899399003990139902399033990439905399063990739908399093991039911399123991339914399153991639917399183991939920399213992239923399243992539926399273992839929399303993139932399333993439935399363993739938399393994039941
  1. /**
  2. * @license
  3. * Copyright 2010-2022 Three.js Authors
  4. * SPDX-License-Identifier: MIT
  5. */
  6. const REVISION = '141'
  7. const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }
  8. const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }
  9. const CullFaceNone = 0
  10. const CullFaceBack = 1
  11. const CullFaceFront = 2
  12. const CullFaceFrontBack = 3
  13. const BasicShadowMap = 0
  14. const PCFShadowMap = 1
  15. const PCFSoftShadowMap = 2
  16. const VSMShadowMap = 3
  17. const FrontSide = 0
  18. const BackSide = 1
  19. const DoubleSide = 2
  20. const FlatShading = 1
  21. const SmoothShading = 2
  22. const NoBlending = 0
  23. const NormalBlending = 1
  24. const AdditiveBlending = 2
  25. const SubtractiveBlending = 3
  26. const MultiplyBlending = 4
  27. const CustomBlending = 5
  28. const AddEquation = 100
  29. const SubtractEquation = 101
  30. const ReverseSubtractEquation = 102
  31. const MinEquation = 103
  32. const MaxEquation = 104
  33. const ZeroFactor = 200
  34. const OneFactor = 201
  35. const SrcColorFactor = 202
  36. const OneMinusSrcColorFactor = 203
  37. const SrcAlphaFactor = 204
  38. const OneMinusSrcAlphaFactor = 205
  39. const DstAlphaFactor = 206
  40. const OneMinusDstAlphaFactor = 207
  41. const DstColorFactor = 208
  42. const OneMinusDstColorFactor = 209
  43. const SrcAlphaSaturateFactor = 210
  44. const NeverDepth = 0
  45. const AlwaysDepth = 1
  46. const LessDepth = 2
  47. const LessEqualDepth = 3
  48. const EqualDepth = 4
  49. const GreaterEqualDepth = 5
  50. const GreaterDepth = 6
  51. const NotEqualDepth = 7
  52. const MultiplyOperation = 0
  53. const MixOperation = 1
  54. const AddOperation = 2
  55. const NoToneMapping = 0
  56. const LinearToneMapping = 1
  57. const ReinhardToneMapping = 2
  58. const CineonToneMapping = 3
  59. const ACESFilmicToneMapping = 4
  60. const CustomToneMapping = 5
  61. const UVMapping = 300
  62. const CubeReflectionMapping = 301
  63. const CubeRefractionMapping = 302
  64. const EquirectangularReflectionMapping = 303
  65. const EquirectangularRefractionMapping = 304
  66. const CubeUVReflectionMapping = 306
  67. const RepeatWrapping = 1000
  68. const ClampToEdgeWrapping = 1001
  69. const MirroredRepeatWrapping = 1002
  70. const NearestFilter = 1003
  71. const NearestMipmapNearestFilter = 1004
  72. const NearestMipMapNearestFilter = 1004
  73. const NearestMipmapLinearFilter = 1005
  74. const NearestMipMapLinearFilter = 1005
  75. const LinearFilter = 1006
  76. const LinearMipmapNearestFilter = 1007
  77. const LinearMipMapNearestFilter = 1007
  78. const LinearMipmapLinearFilter = 1008
  79. const LinearMipMapLinearFilter = 1008
  80. const UnsignedByteType = 1009
  81. const ByteType = 1010
  82. const ShortType = 1011
  83. const UnsignedShortType = 1012
  84. const IntType = 1013
  85. const UnsignedIntType = 1014
  86. const FloatType = 1015
  87. const HalfFloatType = 1016
  88. const UnsignedShort4444Type = 1017
  89. const UnsignedShort5551Type = 1018
  90. const UnsignedInt248Type = 1020
  91. const AlphaFormat = 1021
  92. const RGBFormat = 1022
  93. const RGBAFormat = 1023
  94. const LuminanceFormat = 1024
  95. const LuminanceAlphaFormat = 1025
  96. const DepthFormat = 1026
  97. const DepthStencilFormat = 1027
  98. const RedFormat = 1028
  99. const RedIntegerFormat = 1029
  100. const RGFormat = 1030
  101. const RGIntegerFormat = 1031
  102. const RGBAIntegerFormat = 1033
  103. const RGB_S3TC_DXT1_Format = 33776
  104. const RGBA_S3TC_DXT1_Format = 33777
  105. const RGBA_S3TC_DXT3_Format = 33778
  106. const RGBA_S3TC_DXT5_Format = 33779
  107. const RGB_PVRTC_4BPPV1_Format = 35840
  108. const RGB_PVRTC_2BPPV1_Format = 35841
  109. const RGBA_PVRTC_4BPPV1_Format = 35842
  110. const RGBA_PVRTC_2BPPV1_Format = 35843
  111. const RGB_ETC1_Format = 36196
  112. const RGB_ETC2_Format = 37492
  113. const RGBA_ETC2_EAC_Format = 37496
  114. const RGBA_ASTC_4x4_Format = 37808
  115. const RGBA_ASTC_5x4_Format = 37809
  116. const RGBA_ASTC_5x5_Format = 37810
  117. const RGBA_ASTC_6x5_Format = 37811
  118. const RGBA_ASTC_6x6_Format = 37812
  119. const RGBA_ASTC_8x5_Format = 37813
  120. const RGBA_ASTC_8x6_Format = 37814
  121. const RGBA_ASTC_8x8_Format = 37815
  122. const RGBA_ASTC_10x5_Format = 37816
  123. const RGBA_ASTC_10x6_Format = 37817
  124. const RGBA_ASTC_10x8_Format = 37818
  125. const RGBA_ASTC_10x10_Format = 37819
  126. const RGBA_ASTC_12x10_Format = 37820
  127. const RGBA_ASTC_12x12_Format = 37821
  128. const RGBA_BPTC_Format = 36492
  129. const LoopOnce = 2200
  130. const LoopRepeat = 2201
  131. const LoopPingPong = 2202
  132. const InterpolateDiscrete = 2300
  133. const InterpolateLinear = 2301
  134. const InterpolateSmooth = 2302
  135. const ZeroCurvatureEnding = 2400
  136. const ZeroSlopeEnding = 2401
  137. const WrapAroundEnding = 2402
  138. const NormalAnimationBlendMode = 2500
  139. const AdditiveAnimationBlendMode = 2501
  140. const TrianglesDrawMode = 0
  141. const TriangleStripDrawMode = 1
  142. const TriangleFanDrawMode = 2
  143. const LinearEncoding = 3000
  144. const sRGBEncoding = 3001
  145. const BasicDepthPacking = 3200
  146. const RGBADepthPacking = 3201
  147. const TangentSpaceNormalMap = 0
  148. const ObjectSpaceNormalMap = 1
  149. // Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
  150. const NoColorSpace = ''
  151. const SRGBColorSpace = 'srgb'
  152. const LinearSRGBColorSpace = 'srgb-linear'
  153. const ZeroStencilOp = 0
  154. const KeepStencilOp = 7680
  155. const ReplaceStencilOp = 7681
  156. const IncrementStencilOp = 7682
  157. const DecrementStencilOp = 7683
  158. const IncrementWrapStencilOp = 34055
  159. const DecrementWrapStencilOp = 34056
  160. const InvertStencilOp = 5386
  161. const NeverStencilFunc = 512
  162. const LessStencilFunc = 513
  163. const EqualStencilFunc = 514
  164. const LessEqualStencilFunc = 515
  165. const GreaterStencilFunc = 516
  166. const NotEqualStencilFunc = 517
  167. const GreaterEqualStencilFunc = 518
  168. const AlwaysStencilFunc = 519
  169. const StaticDrawUsage = 35044
  170. const DynamicDrawUsage = 35048
  171. const StreamDrawUsage = 35040
  172. const StaticReadUsage = 35045
  173. const DynamicReadUsage = 35049
  174. const StreamReadUsage = 35041
  175. const StaticCopyUsage = 35046
  176. const DynamicCopyUsage = 35050
  177. const StreamCopyUsage = 35042
  178. const GLSL1 = '100'
  179. const GLSL3 = '300 es'
  180. const _SRGBAFormat = 1035 // fallback for WebGL 1
  181. /**
  182. * https://github.com/mrdoob/eventdispatcher.js/
  183. */
  184. class EventDispatcher {
  185. addEventListener(type, listener) {
  186. if (this._listeners === undefined) this._listeners = {}
  187. const listeners = this._listeners
  188. if (listeners[type] === undefined) {
  189. listeners[type] = []
  190. }
  191. if (listeners[type].indexOf(listener) === -1) {
  192. listeners[type].push(listener)
  193. }
  194. }
  195. hasEventListener(type, listener) {
  196. if (this._listeners === undefined) return false
  197. const listeners = this._listeners
  198. return listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1
  199. }
  200. removeEventListener(type, listener) {
  201. if (this._listeners === undefined) return
  202. const listeners = this._listeners
  203. const listenerArray = listeners[type]
  204. if (listenerArray !== undefined) {
  205. const index = listenerArray.indexOf(listener)
  206. if (index !== -1) {
  207. listenerArray.splice(index, 1)
  208. }
  209. }
  210. }
  211. dispatchEvent(event) {
  212. if (this._listeners === undefined) return
  213. const listeners = this._listeners
  214. const listenerArray = listeners[event.type]
  215. if (listenerArray !== undefined) {
  216. event.target = this
  217. // Make a copy, in case listeners are removed while iterating.
  218. const array = listenerArray.slice(0)
  219. for (let i = 0, l = array.length; i < l; i++) {
  220. array[i].call(this, event)
  221. }
  222. event.target = null
  223. }
  224. }
  225. }
  226. const _lut = []
  227. for (let i = 0; i < 256; i++) {
  228. _lut[i] = (i < 16 ? '0' : '') + i.toString(16)
  229. }
  230. let _seed = 1234567
  231. const DEG2RAD = Math.PI / 180
  232. const RAD2DEG = 180 / Math.PI
  233. // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
  234. function generateUUID() {
  235. const d0 = (Math.random() * 0xffffffff) | 0
  236. const d1 = (Math.random() * 0xffffffff) | 0
  237. const d2 = (Math.random() * 0xffffffff) | 0
  238. const d3 = (Math.random() * 0xffffffff) | 0
  239. const uuid =
  240. _lut[d0 & 0xff] +
  241. _lut[(d0 >> 8) & 0xff] +
  242. _lut[(d0 >> 16) & 0xff] +
  243. _lut[(d0 >> 24) & 0xff] +
  244. '-' +
  245. _lut[d1 & 0xff] +
  246. _lut[(d1 >> 8) & 0xff] +
  247. '-' +
  248. _lut[((d1 >> 16) & 0x0f) | 0x40] +
  249. _lut[(d1 >> 24) & 0xff] +
  250. '-' +
  251. _lut[(d2 & 0x3f) | 0x80] +
  252. _lut[(d2 >> 8) & 0xff] +
  253. '-' +
  254. _lut[(d2 >> 16) & 0xff] +
  255. _lut[(d2 >> 24) & 0xff] +
  256. _lut[d3 & 0xff] +
  257. _lut[(d3 >> 8) & 0xff] +
  258. _lut[(d3 >> 16) & 0xff] +
  259. _lut[(d3 >> 24) & 0xff]
  260. // .toLowerCase() here flattens concatenated strings to save heap memory space.
  261. return uuid.toLowerCase()
  262. }
  263. function clamp(value, min, max) {
  264. return Math.max(min, Math.min(max, value))
  265. }
  266. // compute euclidean modulo of m % n
  267. // https://en.wikipedia.org/wiki/Modulo_operation
  268. function euclideanModulo(n, m) {
  269. return ((n % m) + m) % m
  270. }
  271. // Linear mapping from range <a1, a2> to range <b1, b2>
  272. function mapLinear(x, a1, a2, b1, b2) {
  273. return b1 + ((x - a1) * (b2 - b1)) / (a2 - a1)
  274. }
  275. // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
  276. function inverseLerp(x, y, value) {
  277. if (x !== y) {
  278. return (value - x) / (y - x)
  279. } else {
  280. return 0
  281. }
  282. }
  283. // https://en.wikipedia.org/wiki/Linear_interpolation
  284. function lerp(x, y, t) {
  285. return (1 - t) * x + t * y
  286. }
  287. // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
  288. function damp(x, y, lambda, dt) {
  289. return lerp(x, y, 1 - Math.exp(-lambda * dt))
  290. }
  291. // https://www.desmos.com/calculator/vcsjnyz7x4
  292. function pingpong(x, length = 1) {
  293. return length - Math.abs(euclideanModulo(x, length * 2) - length)
  294. }
  295. // http://en.wikipedia.org/wiki/Smoothstep
  296. function smoothstep(x, min, max) {
  297. if (x <= min) return 0
  298. if (x >= max) return 1
  299. x = (x - min) / (max - min)
  300. return x * x * (3 - 2 * x)
  301. }
  302. function smootherstep(x, min, max) {
  303. if (x <= min) return 0
  304. if (x >= max) return 1
  305. x = (x - min) / (max - min)
  306. return x * x * x * (x * (x * 6 - 15) + 10)
  307. }
  308. // Random integer from <low, high> interval
  309. function randInt(low, high) {
  310. return low + Math.floor(Math.random() * (high - low + 1))
  311. }
  312. // Random float from <low, high> interval
  313. function randFloat(low, high) {
  314. return low + Math.random() * (high - low)
  315. }
  316. // Random float from <-range/2, range/2> interval
  317. function randFloatSpread(range) {
  318. return range * (0.5 - Math.random())
  319. }
  320. // Deterministic pseudo-random float in the interval [ 0, 1 ]
  321. function seededRandom(s) {
  322. if (s !== undefined) _seed = s
  323. // Mulberry32 generator
  324. let t = (_seed += 0x6d2b79f5)
  325. t = Math.imul(t ^ (t >>> 15), t | 1)
  326. t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
  327. return ((t ^ (t >>> 14)) >>> 0) / 4294967296
  328. }
  329. function degToRad(degrees) {
  330. return degrees * DEG2RAD
  331. }
  332. function radToDeg(radians) {
  333. return radians * RAD2DEG
  334. }
  335. function isPowerOfTwo(value) {
  336. return (value & (value - 1)) === 0 && value !== 0
  337. }
  338. function ceilPowerOfTwo(value) {
  339. return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2))
  340. }
  341. function floorPowerOfTwo(value) {
  342. return Math.pow(2, Math.floor(Math.log(value) / Math.LN2))
  343. }
  344. function setQuaternionFromProperEuler(q, a, b, c, order) {
  345. // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
  346. // rotations are applied to the axes in the order specified by 'order'
  347. // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
  348. // angles are in radians
  349. const cos = Math.cos
  350. const sin = Math.sin
  351. const c2 = cos(b / 2)
  352. const s2 = sin(b / 2)
  353. const c13 = cos((a + c) / 2)
  354. const s13 = sin((a + c) / 2)
  355. const c1_3 = cos((a - c) / 2)
  356. const s1_3 = sin((a - c) / 2)
  357. const c3_1 = cos((c - a) / 2)
  358. const s3_1 = sin((c - a) / 2)
  359. switch (order) {
  360. case 'XYX':
  361. q.set(c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13)
  362. break
  363. case 'YZY':
  364. q.set(s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13)
  365. break
  366. case 'ZXZ':
  367. q.set(s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13)
  368. break
  369. case 'XZX':
  370. q.set(c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13)
  371. break
  372. case 'YXY':
  373. q.set(s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13)
  374. break
  375. case 'ZYZ':
  376. q.set(s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13)
  377. break
  378. default:
  379. console.warn('THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order)
  380. }
  381. }
  382. function denormalize$1(value, array) {
  383. switch (array.constructor) {
  384. case Float32Array:
  385. return value
  386. case Uint16Array:
  387. return value / 65535.0
  388. case Uint8Array:
  389. return value / 255.0
  390. case Int16Array:
  391. return Math.max(value / 32767.0, -1.0)
  392. case Int8Array:
  393. return Math.max(value / 127.0, -1.0)
  394. default:
  395. throw new Error('Invalid component type.')
  396. }
  397. }
  398. function normalize(value, array) {
  399. switch (array.constructor) {
  400. case Float32Array:
  401. return value
  402. case Uint16Array:
  403. return Math.round(value * 65535.0)
  404. case Uint8Array:
  405. return Math.round(value * 255.0)
  406. case Int16Array:
  407. return Math.round(value * 32767.0)
  408. case Int8Array:
  409. return Math.round(value * 127.0)
  410. default:
  411. throw new Error('Invalid component type.')
  412. }
  413. }
  414. var MathUtils = /*#__PURE__*/ Object.freeze({
  415. __proto__: null,
  416. DEG2RAD: DEG2RAD,
  417. RAD2DEG: RAD2DEG,
  418. generateUUID: generateUUID,
  419. clamp: clamp,
  420. euclideanModulo: euclideanModulo,
  421. mapLinear: mapLinear,
  422. inverseLerp: inverseLerp,
  423. lerp: lerp,
  424. damp: damp,
  425. pingpong: pingpong,
  426. smoothstep: smoothstep,
  427. smootherstep: smootherstep,
  428. randInt: randInt,
  429. randFloat: randFloat,
  430. randFloatSpread: randFloatSpread,
  431. seededRandom: seededRandom,
  432. degToRad: degToRad,
  433. radToDeg: radToDeg,
  434. isPowerOfTwo: isPowerOfTwo,
  435. ceilPowerOfTwo: ceilPowerOfTwo,
  436. floorPowerOfTwo: floorPowerOfTwo,
  437. setQuaternionFromProperEuler: setQuaternionFromProperEuler,
  438. normalize: normalize,
  439. denormalize: denormalize$1
  440. })
  441. class Vector2 {
  442. constructor(x = 0, y = 0) {
  443. this.isVector2 = true
  444. this.x = x
  445. this.y = y
  446. }
  447. get width() {
  448. return this.x
  449. }
  450. set width(value) {
  451. this.x = value
  452. }
  453. get height() {
  454. return this.y
  455. }
  456. set height(value) {
  457. this.y = value
  458. }
  459. set(x, y) {
  460. this.x = x
  461. this.y = y
  462. return this
  463. }
  464. setScalar(scalar) {
  465. this.x = scalar
  466. this.y = scalar
  467. return this
  468. }
  469. setX(x) {
  470. this.x = x
  471. return this
  472. }
  473. setY(y) {
  474. this.y = y
  475. return this
  476. }
  477. setComponent(index, value) {
  478. switch (index) {
  479. case 0:
  480. this.x = value
  481. break
  482. case 1:
  483. this.y = value
  484. break
  485. default:
  486. throw new Error('index is out of range: ' + index)
  487. }
  488. return this
  489. }
  490. getComponent(index) {
  491. switch (index) {
  492. case 0:
  493. return this.x
  494. case 1:
  495. return this.y
  496. default:
  497. throw new Error('index is out of range: ' + index)
  498. }
  499. }
  500. clone() {
  501. return new this.constructor(this.x, this.y)
  502. }
  503. copy(v) {
  504. this.x = v.x
  505. this.y = v.y
  506. return this
  507. }
  508. add(v, w) {
  509. if (w !== undefined) {
  510. console.warn('THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.')
  511. return this.addVectors(v, w)
  512. }
  513. this.x += v.x
  514. this.y += v.y
  515. return this
  516. }
  517. addScalar(s) {
  518. this.x += s
  519. this.y += s
  520. return this
  521. }
  522. addVectors(a, b) {
  523. this.x = a.x + b.x
  524. this.y = a.y + b.y
  525. return this
  526. }
  527. addScaledVector(v, s) {
  528. this.x += v.x * s
  529. this.y += v.y * s
  530. return this
  531. }
  532. sub(v, w) {
  533. if (w !== undefined) {
  534. console.warn('THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.')
  535. return this.subVectors(v, w)
  536. }
  537. this.x -= v.x
  538. this.y -= v.y
  539. return this
  540. }
  541. subScalar(s) {
  542. this.x -= s
  543. this.y -= s
  544. return this
  545. }
  546. subVectors(a, b) {
  547. this.x = a.x - b.x
  548. this.y = a.y - b.y
  549. return this
  550. }
  551. multiply(v) {
  552. this.x *= v.x
  553. this.y *= v.y
  554. return this
  555. }
  556. multiplyScalar(scalar) {
  557. this.x *= scalar
  558. this.y *= scalar
  559. return this
  560. }
  561. divide(v) {
  562. this.x /= v.x
  563. this.y /= v.y
  564. return this
  565. }
  566. divideScalar(scalar) {
  567. return this.multiplyScalar(1 / scalar)
  568. }
  569. applyMatrix3(m) {
  570. const x = this.x,
  571. y = this.y
  572. const e = m.elements
  573. this.x = e[0] * x + e[3] * y + e[6]
  574. this.y = e[1] * x + e[4] * y + e[7]
  575. return this
  576. }
  577. min(v) {
  578. this.x = Math.min(this.x, v.x)
  579. this.y = Math.min(this.y, v.y)
  580. return this
  581. }
  582. max(v) {
  583. this.x = Math.max(this.x, v.x)
  584. this.y = Math.max(this.y, v.y)
  585. return this
  586. }
  587. clamp(min, max) {
  588. // assumes min < max, componentwise
  589. this.x = Math.max(min.x, Math.min(max.x, this.x))
  590. this.y = Math.max(min.y, Math.min(max.y, this.y))
  591. return this
  592. }
  593. clampScalar(minVal, maxVal) {
  594. this.x = Math.max(minVal, Math.min(maxVal, this.x))
  595. this.y = Math.max(minVal, Math.min(maxVal, this.y))
  596. return this
  597. }
  598. clampLength(min, max) {
  599. const length = this.length()
  600. return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)))
  601. }
  602. floor() {
  603. this.x = Math.floor(this.x)
  604. this.y = Math.floor(this.y)
  605. return this
  606. }
  607. ceil() {
  608. this.x = Math.ceil(this.x)
  609. this.y = Math.ceil(this.y)
  610. return this
  611. }
  612. round() {
  613. this.x = Math.round(this.x)
  614. this.y = Math.round(this.y)
  615. return this
  616. }
  617. roundToZero() {
  618. this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x)
  619. this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y)
  620. return this
  621. }
  622. negate() {
  623. this.x = -this.x
  624. this.y = -this.y
  625. return this
  626. }
  627. dot(v) {
  628. return this.x * v.x + this.y * v.y
  629. }
  630. cross(v) {
  631. return this.x * v.y - this.y * v.x
  632. }
  633. lengthSq() {
  634. return this.x * this.x + this.y * this.y
  635. }
  636. length() {
  637. return Math.sqrt(this.x * this.x + this.y * this.y)
  638. }
  639. manhattanLength() {
  640. return Math.abs(this.x) + Math.abs(this.y)
  641. }
  642. normalize() {
  643. return this.divideScalar(this.length() || 1)
  644. }
  645. angle() {
  646. // computes the angle in radians with respect to the positive x-axis
  647. const angle = Math.atan2(-this.y, -this.x) + Math.PI
  648. return angle
  649. }
  650. distanceTo(v) {
  651. return Math.sqrt(this.distanceToSquared(v))
  652. }
  653. distanceToSquared(v) {
  654. const dx = this.x - v.x,
  655. dy = this.y - v.y
  656. return dx * dx + dy * dy
  657. }
  658. manhattanDistanceTo(v) {
  659. return Math.abs(this.x - v.x) + Math.abs(this.y - v.y)
  660. }
  661. setLength(length) {
  662. return this.normalize().multiplyScalar(length)
  663. }
  664. lerp(v, alpha) {
  665. this.x += (v.x - this.x) * alpha
  666. this.y += (v.y - this.y) * alpha
  667. return this
  668. }
  669. lerpVectors(v1, v2, alpha) {
  670. this.x = v1.x + (v2.x - v1.x) * alpha
  671. this.y = v1.y + (v2.y - v1.y) * alpha
  672. return this
  673. }
  674. equals(v) {
  675. return v.x === this.x && v.y === this.y
  676. }
  677. fromArray(array, offset = 0) {
  678. this.x = array[offset]
  679. this.y = array[offset + 1]
  680. return this
  681. }
  682. toArray(array = [], offset = 0) {
  683. array[offset] = this.x
  684. array[offset + 1] = this.y
  685. return array
  686. }
  687. fromBufferAttribute(attribute, index, offset) {
  688. if (offset !== undefined) {
  689. console.warn('THREE.Vector2: offset has been removed from .fromBufferAttribute().')
  690. }
  691. this.x = attribute.getX(index)
  692. this.y = attribute.getY(index)
  693. return this
  694. }
  695. rotateAround(center, angle) {
  696. const c = Math.cos(angle),
  697. s = Math.sin(angle)
  698. const x = this.x - center.x
  699. const y = this.y - center.y
  700. this.x = x * c - y * s + center.x
  701. this.y = x * s + y * c + center.y
  702. return this
  703. }
  704. random() {
  705. this.x = Math.random()
  706. this.y = Math.random()
  707. return this
  708. }
  709. *[Symbol.iterator]() {
  710. yield this.x
  711. yield this.y
  712. }
  713. }
  714. class Matrix3 {
  715. constructor() {
  716. this.isMatrix3 = true
  717. this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1]
  718. if (arguments.length > 0) {
  719. console.error('THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.')
  720. }
  721. }
  722. set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
  723. const te = this.elements
  724. te[0] = n11
  725. te[1] = n21
  726. te[2] = n31
  727. te[3] = n12
  728. te[4] = n22
  729. te[5] = n32
  730. te[6] = n13
  731. te[7] = n23
  732. te[8] = n33
  733. return this
  734. }
  735. identity() {
  736. this.set(1, 0, 0, 0, 1, 0, 0, 0, 1)
  737. return this
  738. }
  739. copy(m) {
  740. const te = this.elements
  741. const me = m.elements
  742. te[0] = me[0]
  743. te[1] = me[1]
  744. te[2] = me[2]
  745. te[3] = me[3]
  746. te[4] = me[4]
  747. te[5] = me[5]
  748. te[6] = me[6]
  749. te[7] = me[7]
  750. te[8] = me[8]
  751. return this
  752. }
  753. extractBasis(xAxis, yAxis, zAxis) {
  754. xAxis.setFromMatrix3Column(this, 0)
  755. yAxis.setFromMatrix3Column(this, 1)
  756. zAxis.setFromMatrix3Column(this, 2)
  757. return this
  758. }
  759. setFromMatrix4(m) {
  760. const me = m.elements
  761. this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10])
  762. return this
  763. }
  764. multiply(m) {
  765. return this.multiplyMatrices(this, m)
  766. }
  767. premultiply(m) {
  768. return this.multiplyMatrices(m, this)
  769. }
  770. multiplyMatrices(a, b) {
  771. const ae = a.elements
  772. const be = b.elements
  773. const te = this.elements
  774. const a11 = ae[0],
  775. a12 = ae[3],
  776. a13 = ae[6]
  777. const a21 = ae[1],
  778. a22 = ae[4],
  779. a23 = ae[7]
  780. const a31 = ae[2],
  781. a32 = ae[5],
  782. a33 = ae[8]
  783. const b11 = be[0],
  784. b12 = be[3],
  785. b13 = be[6]
  786. const b21 = be[1],
  787. b22 = be[4],
  788. b23 = be[7]
  789. const b31 = be[2],
  790. b32 = be[5],
  791. b33 = be[8]
  792. te[0] = a11 * b11 + a12 * b21 + a13 * b31
  793. te[3] = a11 * b12 + a12 * b22 + a13 * b32
  794. te[6] = a11 * b13 + a12 * b23 + a13 * b33
  795. te[1] = a21 * b11 + a22 * b21 + a23 * b31
  796. te[4] = a21 * b12 + a22 * b22 + a23 * b32
  797. te[7] = a21 * b13 + a22 * b23 + a23 * b33
  798. te[2] = a31 * b11 + a32 * b21 + a33 * b31
  799. te[5] = a31 * b12 + a32 * b22 + a33 * b32
  800. te[8] = a31 * b13 + a32 * b23 + a33 * b33
  801. return this
  802. }
  803. multiplyScalar(s) {
  804. const te = this.elements
  805. te[0] *= s
  806. te[3] *= s
  807. te[6] *= s
  808. te[1] *= s
  809. te[4] *= s
  810. te[7] *= s
  811. te[2] *= s
  812. te[5] *= s
  813. te[8] *= s
  814. return this
  815. }
  816. determinant() {
  817. const te = this.elements
  818. const a = te[0],
  819. b = te[1],
  820. c = te[2],
  821. d = te[3],
  822. e = te[4],
  823. f = te[5],
  824. g = te[6],
  825. h = te[7],
  826. i = te[8]
  827. return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g
  828. }
  829. invert() {
  830. const te = this.elements,
  831. n11 = te[0],
  832. n21 = te[1],
  833. n31 = te[2],
  834. n12 = te[3],
  835. n22 = te[4],
  836. n32 = te[5],
  837. n13 = te[6],
  838. n23 = te[7],
  839. n33 = te[8],
  840. t11 = n33 * n22 - n32 * n23,
  841. t12 = n32 * n13 - n33 * n12,
  842. t13 = n23 * n12 - n22 * n13,
  843. det = n11 * t11 + n21 * t12 + n31 * t13
  844. if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0)
  845. const detInv = 1 / det
  846. te[0] = t11 * detInv
  847. te[1] = (n31 * n23 - n33 * n21) * detInv
  848. te[2] = (n32 * n21 - n31 * n22) * detInv
  849. te[3] = t12 * detInv
  850. te[4] = (n33 * n11 - n31 * n13) * detInv
  851. te[5] = (n31 * n12 - n32 * n11) * detInv
  852. te[6] = t13 * detInv
  853. te[7] = (n21 * n13 - n23 * n11) * detInv
  854. te[8] = (n22 * n11 - n21 * n12) * detInv
  855. return this
  856. }
  857. transpose() {
  858. let tmp
  859. const m = this.elements
  860. tmp = m[1]
  861. m[1] = m[3]
  862. m[3] = tmp
  863. tmp = m[2]
  864. m[2] = m[6]
  865. m[6] = tmp
  866. tmp = m[5]
  867. m[5] = m[7]
  868. m[7] = tmp
  869. return this
  870. }
  871. getNormalMatrix(matrix4) {
  872. return this.setFromMatrix4(matrix4)
  873. .invert()
  874. .transpose()
  875. }
  876. transposeIntoArray(r) {
  877. const m = this.elements
  878. r[0] = m[0]
  879. r[1] = m[3]
  880. r[2] = m[6]
  881. r[3] = m[1]
  882. r[4] = m[4]
  883. r[5] = m[7]
  884. r[6] = m[2]
  885. r[7] = m[5]
  886. r[8] = m[8]
  887. return this
  888. }
  889. setUvTransform(tx, ty, sx, sy, rotation, cx, cy) {
  890. const c = Math.cos(rotation)
  891. const s = Math.sin(rotation)
  892. this.set(sx * c, sx * s, -sx * (c * cx + s * cy) + cx + tx, -sy * s, sy * c, -sy * (-s * cx + c * cy) + cy + ty, 0, 0, 1)
  893. return this
  894. }
  895. scale(sx, sy) {
  896. const te = this.elements
  897. te[0] *= sx
  898. te[3] *= sx
  899. te[6] *= sx
  900. te[1] *= sy
  901. te[4] *= sy
  902. te[7] *= sy
  903. return this
  904. }
  905. rotate(theta) {
  906. const c = Math.cos(theta)
  907. const s = Math.sin(theta)
  908. const te = this.elements
  909. const a11 = te[0],
  910. a12 = te[3],
  911. a13 = te[6]
  912. const a21 = te[1],
  913. a22 = te[4],
  914. a23 = te[7]
  915. te[0] = c * a11 + s * a21
  916. te[3] = c * a12 + s * a22
  917. te[6] = c * a13 + s * a23
  918. te[1] = -s * a11 + c * a21
  919. te[4] = -s * a12 + c * a22
  920. te[7] = -s * a13 + c * a23
  921. return this
  922. }
  923. translate(tx, ty) {
  924. const te = this.elements
  925. te[0] += tx * te[2]
  926. te[3] += tx * te[5]
  927. te[6] += tx * te[8]
  928. te[1] += ty * te[2]
  929. te[4] += ty * te[5]
  930. te[7] += ty * te[8]
  931. return this
  932. }
  933. equals(matrix) {
  934. const te = this.elements
  935. const me = matrix.elements
  936. for (let i = 0; i < 9; i++) {
  937. if (te[i] !== me[i]) return false
  938. }
  939. return true
  940. }
  941. fromArray(array, offset = 0) {
  942. for (let i = 0; i < 9; i++) {
  943. this.elements[i] = array[i + offset]
  944. }
  945. return this
  946. }
  947. toArray(array = [], offset = 0) {
  948. const te = this.elements
  949. array[offset] = te[0]
  950. array[offset + 1] = te[1]
  951. array[offset + 2] = te[2]
  952. array[offset + 3] = te[3]
  953. array[offset + 4] = te[4]
  954. array[offset + 5] = te[5]
  955. array[offset + 6] = te[6]
  956. array[offset + 7] = te[7]
  957. array[offset + 8] = te[8]
  958. return array
  959. }
  960. clone() {
  961. return new this.constructor().fromArray(this.elements)
  962. }
  963. }
  964. function arrayNeedsUint32(array) {
  965. // assumes larger values usually on last
  966. for (let i = array.length - 1; i >= 0; --i) {
  967. if (array[i] > 65535) return true
  968. }
  969. return false
  970. }
  971. const TYPED_ARRAYS = {
  972. Int8Array: Int8Array,
  973. Uint8Array: Uint8Array,
  974. Uint8ClampedArray: Uint8ClampedArray,
  975. Int16Array: Int16Array,
  976. Uint16Array: Uint16Array,
  977. Int32Array: Int32Array,
  978. Uint32Array: Uint32Array,
  979. Float32Array: Float32Array,
  980. Float64Array: Float64Array
  981. }
  982. function getTypedArray(type, buffer) {
  983. return new TYPED_ARRAYS[type](buffer)
  984. }
  985. function createElementNS(name) {
  986. return document.createElementNS('http://www.w3.org/1999/xhtml', name)
  987. }
  988. function SRGBToLinear(c) {
  989. return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4)
  990. }
  991. function LinearToSRGB(c) {
  992. return c < 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 0.41666) - 0.055
  993. }
  994. // JavaScript RGB-to-RGB transforms, defined as
  995. // FN[InputColorSpace][OutputColorSpace] callback functions.
  996. const FN = {
  997. [SRGBColorSpace]: { [LinearSRGBColorSpace]: SRGBToLinear },
  998. [LinearSRGBColorSpace]: { [SRGBColorSpace]: LinearToSRGB }
  999. }
  1000. const ColorManagement = {
  1001. legacyMode: true,
  1002. get workingColorSpace() {
  1003. return LinearSRGBColorSpace
  1004. },
  1005. set workingColorSpace(colorSpace) {
  1006. console.warn('THREE.ColorManagement: .workingColorSpace is readonly.')
  1007. },
  1008. convert: function(color, sourceColorSpace, targetColorSpace) {
  1009. if (this.legacyMode || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) {
  1010. return color
  1011. }
  1012. if (FN[sourceColorSpace] && FN[sourceColorSpace][targetColorSpace] !== undefined) {
  1013. const fn = FN[sourceColorSpace][targetColorSpace]
  1014. color.r = fn(color.r)
  1015. color.g = fn(color.g)
  1016. color.b = fn(color.b)
  1017. return color
  1018. }
  1019. throw new Error('Unsupported color space conversion.')
  1020. },
  1021. fromWorkingColorSpace: function(color, targetColorSpace) {
  1022. return this.convert(color, this.workingColorSpace, targetColorSpace)
  1023. },
  1024. toWorkingColorSpace: function(color, sourceColorSpace) {
  1025. return this.convert(color, sourceColorSpace, this.workingColorSpace)
  1026. }
  1027. }
  1028. const _colorKeywords = {
  1029. aliceblue: 0xf0f8ff,
  1030. antiquewhite: 0xfaebd7,
  1031. aqua: 0x00ffff,
  1032. aquamarine: 0x7fffd4,
  1033. azure: 0xf0ffff,
  1034. beige: 0xf5f5dc,
  1035. bisque: 0xffe4c4,
  1036. black: 0x000000,
  1037. blanchedalmond: 0xffebcd,
  1038. blue: 0x0000ff,
  1039. blueviolet: 0x8a2be2,
  1040. brown: 0xa52a2a,
  1041. burlywood: 0xdeb887,
  1042. cadetblue: 0x5f9ea0,
  1043. chartreuse: 0x7fff00,
  1044. chocolate: 0xd2691e,
  1045. coral: 0xff7f50,
  1046. cornflowerblue: 0x6495ed,
  1047. cornsilk: 0xfff8dc,
  1048. crimson: 0xdc143c,
  1049. cyan: 0x00ffff,
  1050. darkblue: 0x00008b,
  1051. darkcyan: 0x008b8b,
  1052. darkgoldenrod: 0xb8860b,
  1053. darkgray: 0xa9a9a9,
  1054. darkgreen: 0x006400,
  1055. darkgrey: 0xa9a9a9,
  1056. darkkhaki: 0xbdb76b,
  1057. darkmagenta: 0x8b008b,
  1058. darkolivegreen: 0x556b2f,
  1059. darkorange: 0xff8c00,
  1060. darkorchid: 0x9932cc,
  1061. darkred: 0x8b0000,
  1062. darksalmon: 0xe9967a,
  1063. darkseagreen: 0x8fbc8f,
  1064. darkslateblue: 0x483d8b,
  1065. darkslategray: 0x2f4f4f,
  1066. darkslategrey: 0x2f4f4f,
  1067. darkturquoise: 0x00ced1,
  1068. darkviolet: 0x9400d3,
  1069. deeppink: 0xff1493,
  1070. deepskyblue: 0x00bfff,
  1071. dimgray: 0x696969,
  1072. dimgrey: 0x696969,
  1073. dodgerblue: 0x1e90ff,
  1074. firebrick: 0xb22222,
  1075. floralwhite: 0xfffaf0,
  1076. forestgreen: 0x228b22,
  1077. fuchsia: 0xff00ff,
  1078. gainsboro: 0xdcdcdc,
  1079. ghostwhite: 0xf8f8ff,
  1080. gold: 0xffd700,
  1081. goldenrod: 0xdaa520,
  1082. gray: 0x808080,
  1083. green: 0x008000,
  1084. greenyellow: 0xadff2f,
  1085. grey: 0x808080,
  1086. honeydew: 0xf0fff0,
  1087. hotpink: 0xff69b4,
  1088. indianred: 0xcd5c5c,
  1089. indigo: 0x4b0082,
  1090. ivory: 0xfffff0,
  1091. khaki: 0xf0e68c,
  1092. lavender: 0xe6e6fa,
  1093. lavenderblush: 0xfff0f5,
  1094. lawngreen: 0x7cfc00,
  1095. lemonchiffon: 0xfffacd,
  1096. lightblue: 0xadd8e6,
  1097. lightcoral: 0xf08080,
  1098. lightcyan: 0xe0ffff,
  1099. lightgoldenrodyellow: 0xfafad2,
  1100. lightgray: 0xd3d3d3,
  1101. lightgreen: 0x90ee90,
  1102. lightgrey: 0xd3d3d3,
  1103. lightpink: 0xffb6c1,
  1104. lightsalmon: 0xffa07a,
  1105. lightseagreen: 0x20b2aa,
  1106. lightskyblue: 0x87cefa,
  1107. lightslategray: 0x778899,
  1108. lightslategrey: 0x778899,
  1109. lightsteelblue: 0xb0c4de,
  1110. lightyellow: 0xffffe0,
  1111. lime: 0x00ff00,
  1112. limegreen: 0x32cd32,
  1113. linen: 0xfaf0e6,
  1114. magenta: 0xff00ff,
  1115. maroon: 0x800000,
  1116. mediumaquamarine: 0x66cdaa,
  1117. mediumblue: 0x0000cd,
  1118. mediumorchid: 0xba55d3,
  1119. mediumpurple: 0x9370db,
  1120. mediumseagreen: 0x3cb371,
  1121. mediumslateblue: 0x7b68ee,
  1122. mediumspringgreen: 0x00fa9a,
  1123. mediumturquoise: 0x48d1cc,
  1124. mediumvioletred: 0xc71585,
  1125. midnightblue: 0x191970,
  1126. mintcream: 0xf5fffa,
  1127. mistyrose: 0xffe4e1,
  1128. moccasin: 0xffe4b5,
  1129. navajowhite: 0xffdead,
  1130. navy: 0x000080,
  1131. oldlace: 0xfdf5e6,
  1132. olive: 0x808000,
  1133. olivedrab: 0x6b8e23,
  1134. orange: 0xffa500,
  1135. orangered: 0xff4500,
  1136. orchid: 0xda70d6,
  1137. palegoldenrod: 0xeee8aa,
  1138. palegreen: 0x98fb98,
  1139. paleturquoise: 0xafeeee,
  1140. palevioletred: 0xdb7093,
  1141. papayawhip: 0xffefd5,
  1142. peachpuff: 0xffdab9,
  1143. peru: 0xcd853f,
  1144. pink: 0xffc0cb,
  1145. plum: 0xdda0dd,
  1146. powderblue: 0xb0e0e6,
  1147. purple: 0x800080,
  1148. rebeccapurple: 0x663399,
  1149. red: 0xff0000,
  1150. rosybrown: 0xbc8f8f,
  1151. royalblue: 0x4169e1,
  1152. saddlebrown: 0x8b4513,
  1153. salmon: 0xfa8072,
  1154. sandybrown: 0xf4a460,
  1155. seagreen: 0x2e8b57,
  1156. seashell: 0xfff5ee,
  1157. sienna: 0xa0522d,
  1158. silver: 0xc0c0c0,
  1159. skyblue: 0x87ceeb,
  1160. slateblue: 0x6a5acd,
  1161. slategray: 0x708090,
  1162. slategrey: 0x708090,
  1163. snow: 0xfffafa,
  1164. springgreen: 0x00ff7f,
  1165. steelblue: 0x4682b4,
  1166. tan: 0xd2b48c,
  1167. teal: 0x008080,
  1168. thistle: 0xd8bfd8,
  1169. tomato: 0xff6347,
  1170. turquoise: 0x40e0d0,
  1171. violet: 0xee82ee,
  1172. wheat: 0xf5deb3,
  1173. white: 0xffffff,
  1174. whitesmoke: 0xf5f5f5,
  1175. yellow: 0xffff00,
  1176. yellowgreen: 0x9acd32
  1177. }
  1178. const _rgb = { r: 0, g: 0, b: 0 }
  1179. const _hslA = { h: 0, s: 0, l: 0 }
  1180. const _hslB = { h: 0, s: 0, l: 0 }
  1181. function hue2rgb(p, q, t) {
  1182. if (t < 0) t += 1
  1183. if (t > 1) t -= 1
  1184. if (t < 1 / 6) return p + (q - p) * 6 * t
  1185. if (t < 1 / 2) return q
  1186. if (t < 2 / 3) return p + (q - p) * 6 * (2 / 3 - t)
  1187. return p
  1188. }
  1189. function toComponents(source, target) {
  1190. target.r = source.r
  1191. target.g = source.g
  1192. target.b = source.b
  1193. return target
  1194. }
  1195. class Color {
  1196. constructor(r, g, b) {
  1197. this.isColor = true
  1198. this.r = 1
  1199. this.g = 1
  1200. this.b = 1
  1201. if (g === undefined && b === undefined) {
  1202. // r is THREE.Color, hex or string
  1203. return this.set(r)
  1204. }
  1205. return this.setRGB(r, g, b)
  1206. }
  1207. set(value) {
  1208. if (value && value.isColor) {
  1209. this.copy(value)
  1210. } else if (typeof value === 'number') {
  1211. this.setHex(value)
  1212. } else if (typeof value === 'string') {
  1213. this.setStyle(value)
  1214. }
  1215. return this
  1216. }
  1217. setScalar(scalar) {
  1218. this.r = scalar
  1219. this.g = scalar
  1220. this.b = scalar
  1221. return this
  1222. }
  1223. setHex(hex, colorSpace = SRGBColorSpace) {
  1224. hex = Math.floor(hex)
  1225. this.r = ((hex >> 16) & 255) / 255
  1226. this.g = ((hex >> 8) & 255) / 255
  1227. this.b = (hex & 255) / 255
  1228. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1229. return this
  1230. }
  1231. setRGB(r, g, b, colorSpace = LinearSRGBColorSpace) {
  1232. this.r = r
  1233. this.g = g
  1234. this.b = b
  1235. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1236. return this
  1237. }
  1238. setHSL(h, s, l, colorSpace = LinearSRGBColorSpace) {
  1239. // h,s,l ranges are in 0.0 - 1.0
  1240. h = euclideanModulo(h, 1)
  1241. s = clamp(s, 0, 1)
  1242. l = clamp(l, 0, 1)
  1243. if (s === 0) {
  1244. this.r = this.g = this.b = l
  1245. } else {
  1246. const p = l <= 0.5 ? l * (1 + s) : l + s - l * s
  1247. const q = 2 * l - p
  1248. this.r = hue2rgb(q, p, h + 1 / 3)
  1249. this.g = hue2rgb(q, p, h)
  1250. this.b = hue2rgb(q, p, h - 1 / 3)
  1251. }
  1252. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1253. return this
  1254. }
  1255. setStyle(style, colorSpace = SRGBColorSpace) {
  1256. function handleAlpha(string) {
  1257. if (string === undefined) return
  1258. if (parseFloat(string) < 1) {
  1259. console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.')
  1260. }
  1261. }
  1262. let m
  1263. if ((m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(style))) {
  1264. // rgb / hsl
  1265. let color
  1266. const name = m[1]
  1267. const components = m[2]
  1268. switch (name) {
  1269. case 'rgb':
  1270. case 'rgba':
  1271. if ((color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components))) {
  1272. // rgb(255,0,0) rgba(255,0,0,0.5)
  1273. this.r = Math.min(255, parseInt(color[1], 10)) / 255
  1274. this.g = Math.min(255, parseInt(color[2], 10)) / 255
  1275. this.b = Math.min(255, parseInt(color[3], 10)) / 255
  1276. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1277. handleAlpha(color[4])
  1278. return this
  1279. }
  1280. if ((color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components))) {
  1281. // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
  1282. this.r = Math.min(100, parseInt(color[1], 10)) / 100
  1283. this.g = Math.min(100, parseInt(color[2], 10)) / 100
  1284. this.b = Math.min(100, parseInt(color[3], 10)) / 100
  1285. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1286. handleAlpha(color[4])
  1287. return this
  1288. }
  1289. break
  1290. case 'hsl':
  1291. case 'hsla':
  1292. if ((color = /^\s*(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components))) {
  1293. // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
  1294. const h = parseFloat(color[1]) / 360
  1295. const s = parseInt(color[2], 10) / 100
  1296. const l = parseInt(color[3], 10) / 100
  1297. handleAlpha(color[4])
  1298. return this.setHSL(h, s, l, colorSpace)
  1299. }
  1300. break
  1301. }
  1302. } else if ((m = /^\#([A-Fa-f\d]+)$/.exec(style))) {
  1303. // hex color
  1304. const hex = m[1]
  1305. const size = hex.length
  1306. if (size === 3) {
  1307. // #ff0
  1308. this.r = parseInt(hex.charAt(0) + hex.charAt(0), 16) / 255
  1309. this.g = parseInt(hex.charAt(1) + hex.charAt(1), 16) / 255
  1310. this.b = parseInt(hex.charAt(2) + hex.charAt(2), 16) / 255
  1311. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1312. return this
  1313. } else if (size === 6) {
  1314. // #ff0000
  1315. this.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255
  1316. this.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255
  1317. this.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255
  1318. ColorManagement.toWorkingColorSpace(this, colorSpace)
  1319. return this
  1320. }
  1321. }
  1322. if (style && style.length > 0) {
  1323. return this.setColorName(style, colorSpace)
  1324. }
  1325. return this
  1326. }
  1327. setColorName(style, colorSpace = SRGBColorSpace) {
  1328. // color keywords
  1329. const hex = _colorKeywords[style.toLowerCase()]
  1330. if (hex !== undefined) {
  1331. // red
  1332. this.setHex(hex, colorSpace)
  1333. } else {
  1334. // unknown color
  1335. console.warn('THREE.Color: Unknown color ' + style)
  1336. }
  1337. return this
  1338. }
  1339. clone() {
  1340. return new this.constructor(this.r, this.g, this.b)
  1341. }
  1342. copy(color) {
  1343. this.r = color.r
  1344. this.g = color.g
  1345. this.b = color.b
  1346. return this
  1347. }
  1348. copySRGBToLinear(color) {
  1349. this.r = SRGBToLinear(color.r)
  1350. this.g = SRGBToLinear(color.g)
  1351. this.b = SRGBToLinear(color.b)
  1352. return this
  1353. }
  1354. copyLinearToSRGB(color) {
  1355. this.r = LinearToSRGB(color.r)
  1356. this.g = LinearToSRGB(color.g)
  1357. this.b = LinearToSRGB(color.b)
  1358. return this
  1359. }
  1360. convertSRGBToLinear() {
  1361. this.copySRGBToLinear(this)
  1362. return this
  1363. }
  1364. convertLinearToSRGB() {
  1365. this.copyLinearToSRGB(this)
  1366. return this
  1367. }
  1368. getHex(colorSpace = SRGBColorSpace) {
  1369. ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace)
  1370. return (clamp(_rgb.r * 255, 0, 255) << 16) ^ (clamp(_rgb.g * 255, 0, 255) << 8) ^ (clamp(_rgb.b * 255, 0, 255) << 0)
  1371. }
  1372. getHexString(colorSpace = SRGBColorSpace) {
  1373. return ('000000' + this.getHex(colorSpace).toString(16)).slice(-6)
  1374. }
  1375. getHSL(target, colorSpace = LinearSRGBColorSpace) {
  1376. // h,s,l ranges are in 0.0 - 1.0
  1377. ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace)
  1378. const r = _rgb.r,
  1379. g = _rgb.g,
  1380. b = _rgb.b
  1381. const max = Math.max(r, g, b)
  1382. const min = Math.min(r, g, b)
  1383. let hue, saturation
  1384. const lightness = (min + max) / 2.0
  1385. if (min === max) {
  1386. hue = 0
  1387. saturation = 0
  1388. } else {
  1389. const delta = max - min
  1390. saturation = lightness <= 0.5 ? delta / (max + min) : delta / (2 - max - min)
  1391. switch (max) {
  1392. case r:
  1393. hue = (g - b) / delta + (g < b ? 6 : 0)
  1394. break
  1395. case g:
  1396. hue = (b - r) / delta + 2
  1397. break
  1398. case b:
  1399. hue = (r - g) / delta + 4
  1400. break
  1401. }
  1402. hue /= 6
  1403. }
  1404. target.h = hue
  1405. target.s = saturation
  1406. target.l = lightness
  1407. return target
  1408. }
  1409. getRGB(target, colorSpace = LinearSRGBColorSpace) {
  1410. ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace)
  1411. target.r = _rgb.r
  1412. target.g = _rgb.g
  1413. target.b = _rgb.b
  1414. return target
  1415. }
  1416. getStyle(colorSpace = SRGBColorSpace) {
  1417. ColorManagement.fromWorkingColorSpace(toComponents(this, _rgb), colorSpace)
  1418. if (colorSpace !== SRGBColorSpace) {
  1419. // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
  1420. return `color(${colorSpace} ${_rgb.r} ${_rgb.g} ${_rgb.b})`
  1421. }
  1422. return `rgb(${(_rgb.r * 255) | 0},${(_rgb.g * 255) | 0},${(_rgb.b * 255) | 0})`
  1423. }
  1424. offsetHSL(h, s, l) {
  1425. this.getHSL(_hslA)
  1426. _hslA.h += h
  1427. _hslA.s += s
  1428. _hslA.l += l
  1429. this.setHSL(_hslA.h, _hslA.s, _hslA.l)
  1430. return this
  1431. }
  1432. add(color) {
  1433. this.r += color.r
  1434. this.g += color.g
  1435. this.b += color.b
  1436. return this
  1437. }
  1438. addColors(color1, color2) {
  1439. this.r = color1.r + color2.r
  1440. this.g = color1.g + color2.g
  1441. this.b = color1.b + color2.b
  1442. return this
  1443. }
  1444. addScalar(s) {
  1445. this.r += s
  1446. this.g += s
  1447. this.b += s
  1448. return this
  1449. }
  1450. sub(color) {
  1451. this.r = Math.max(0, this.r - color.r)
  1452. this.g = Math.max(0, this.g - color.g)
  1453. this.b = Math.max(0, this.b - color.b)
  1454. return this
  1455. }
  1456. multiply(color) {
  1457. this.r *= color.r
  1458. this.g *= color.g
  1459. this.b *= color.b
  1460. return this
  1461. }
  1462. multiplyScalar(s) {
  1463. this.r *= s
  1464. this.g *= s
  1465. this.b *= s
  1466. return this
  1467. }
  1468. lerp(color, alpha) {
  1469. this.r += (color.r - this.r) * alpha
  1470. this.g += (color.g - this.g) * alpha
  1471. this.b += (color.b - this.b) * alpha
  1472. return this
  1473. }
  1474. lerpColors(color1, color2, alpha) {
  1475. this.r = color1.r + (color2.r - color1.r) * alpha
  1476. this.g = color1.g + (color2.g - color1.g) * alpha
  1477. this.b = color1.b + (color2.b - color1.b) * alpha
  1478. return this
  1479. }
  1480. lerpHSL(color, alpha) {
  1481. this.getHSL(_hslA)
  1482. color.getHSL(_hslB)
  1483. const h = lerp(_hslA.h, _hslB.h, alpha)
  1484. const s = lerp(_hslA.s, _hslB.s, alpha)
  1485. const l = lerp(_hslA.l, _hslB.l, alpha)
  1486. this.setHSL(h, s, l)
  1487. return this
  1488. }
  1489. equals(c) {
  1490. return c.r === this.r && c.g === this.g && c.b === this.b
  1491. }
  1492. fromArray(array, offset = 0) {
  1493. this.r = array[offset]
  1494. this.g = array[offset + 1]
  1495. this.b = array[offset + 2]
  1496. return this
  1497. }
  1498. toArray(array = [], offset = 0) {
  1499. array[offset] = this.r
  1500. array[offset + 1] = this.g
  1501. array[offset + 2] = this.b
  1502. return array
  1503. }
  1504. fromBufferAttribute(attribute, index) {
  1505. this.r = attribute.getX(index)
  1506. this.g = attribute.getY(index)
  1507. this.b = attribute.getZ(index)
  1508. if (attribute.normalized === true) {
  1509. // assuming Uint8Array
  1510. this.r /= 255
  1511. this.g /= 255
  1512. this.b /= 255
  1513. }
  1514. return this
  1515. }
  1516. toJSON() {
  1517. return this.getHex()
  1518. }
  1519. *[Symbol.iterator]() {
  1520. yield this.r
  1521. yield this.g
  1522. yield this.b
  1523. }
  1524. }
  1525. Color.NAMES = _colorKeywords
  1526. let _canvas
  1527. class ImageUtils {
  1528. static getDataURL(image) {
  1529. if (/^data:/i.test(image.src)) {
  1530. return image.src
  1531. }
  1532. if (typeof HTMLCanvasElement == 'undefined') {
  1533. return image.src
  1534. }
  1535. let canvas
  1536. if (image instanceof HTMLCanvasElement) {
  1537. canvas = image
  1538. } else {
  1539. if (_canvas === undefined) _canvas = createElementNS('canvas')
  1540. _canvas.width = image.width
  1541. _canvas.height = image.height
  1542. const context = _canvas.getContext('2d')
  1543. if (image instanceof ImageData) {
  1544. context.putImageData(image, 0, 0)
  1545. } else {
  1546. context.drawImage(image, 0, 0, image.width, image.height)
  1547. }
  1548. canvas = _canvas
  1549. }
  1550. if (canvas.width > 2048 || canvas.height > 2048) {
  1551. console.warn('THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image)
  1552. return canvas.toDataURL('image/jpeg', 0.6)
  1553. } else {
  1554. return canvas.toDataURL('image/png')
  1555. }
  1556. }
  1557. static sRGBToLinear(image) {
  1558. if (
  1559. (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
  1560. (typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
  1561. (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)
  1562. ) {
  1563. const canvas = createElementNS('canvas')
  1564. canvas.width = image.width
  1565. canvas.height = image.height
  1566. const context = canvas.getContext('2d')
  1567. context.drawImage(image, 0, 0, image.width, image.height)
  1568. const imageData = context.getImageData(0, 0, image.width, image.height)
  1569. const data = imageData.data
  1570. for (let i = 0; i < data.length; i++) {
  1571. data[i] = SRGBToLinear(data[i] / 255) * 255
  1572. }
  1573. context.putImageData(imageData, 0, 0)
  1574. return canvas
  1575. } else if (image.data) {
  1576. const data = image.data.slice(0)
  1577. for (let i = 0; i < data.length; i++) {
  1578. if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) {
  1579. data[i] = Math.floor(SRGBToLinear(data[i] / 255) * 255)
  1580. } else {
  1581. // assuming float
  1582. data[i] = SRGBToLinear(data[i])
  1583. }
  1584. }
  1585. return {
  1586. data: data,
  1587. width: image.width,
  1588. height: image.height
  1589. }
  1590. } else {
  1591. console.warn('THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.')
  1592. return image
  1593. }
  1594. }
  1595. }
  1596. class Source {
  1597. constructor(data = null) {
  1598. this.isSource = true
  1599. this.uuid = generateUUID()
  1600. this.data = data
  1601. this.version = 0
  1602. }
  1603. set needsUpdate(value) {
  1604. if (value === true) this.version++
  1605. }
  1606. toJSON(meta) {
  1607. const isRootObject = meta === undefined || typeof meta === 'string'
  1608. if (!isRootObject && meta.images[this.uuid] !== undefined) {
  1609. return meta.images[this.uuid]
  1610. }
  1611. const output = {
  1612. uuid: this.uuid,
  1613. url: ''
  1614. }
  1615. const data = this.data
  1616. if (data !== null) {
  1617. let url
  1618. if (Array.isArray(data)) {
  1619. // cube texture
  1620. url = []
  1621. for (let i = 0, l = data.length; i < l; i++) {
  1622. if (data[i].isDataTexture) {
  1623. url.push(serializeImage(data[i].image))
  1624. } else {
  1625. url.push(serializeImage(data[i]))
  1626. }
  1627. }
  1628. } else {
  1629. // texture
  1630. url = serializeImage(data)
  1631. }
  1632. output.url = url
  1633. }
  1634. if (!isRootObject) {
  1635. meta.images[this.uuid] = output
  1636. }
  1637. return output
  1638. }
  1639. }
  1640. function serializeImage(image) {
  1641. if (
  1642. (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
  1643. (typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
  1644. (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)
  1645. ) {
  1646. // default images
  1647. return ImageUtils.getDataURL(image)
  1648. } else {
  1649. if (image.data) {
  1650. // images of DataTexture
  1651. return {
  1652. data: Array.prototype.slice.call(image.data),
  1653. width: image.width,
  1654. height: image.height,
  1655. type: image.data.constructor.name
  1656. }
  1657. } else {
  1658. console.warn('THREE.Texture: Unable to serialize Texture.')
  1659. return {}
  1660. }
  1661. }
  1662. }
  1663. let textureId = 0
  1664. class Texture extends EventDispatcher {
  1665. constructor(
  1666. image = Texture.DEFAULT_IMAGE,
  1667. mapping = Texture.DEFAULT_MAPPING,
  1668. wrapS = ClampToEdgeWrapping,
  1669. wrapT = ClampToEdgeWrapping,
  1670. magFilter = LinearFilter,
  1671. minFilter = LinearMipmapLinearFilter,
  1672. format = RGBAFormat,
  1673. type = UnsignedByteType,
  1674. anisotropy = 1,
  1675. encoding = LinearEncoding
  1676. ) {
  1677. super()
  1678. this.isTexture = true
  1679. Object.defineProperty(this, 'id', { value: textureId++ })
  1680. this.uuid = generateUUID()
  1681. this.name = ''
  1682. this.source = new Source(image)
  1683. this.mipmaps = []
  1684. this.mapping = mapping
  1685. this.wrapS = wrapS
  1686. this.wrapT = wrapT
  1687. this.magFilter = magFilter
  1688. this.minFilter = minFilter
  1689. this.anisotropy = anisotropy
  1690. this.format = format
  1691. this.internalFormat = null
  1692. this.type = type
  1693. this.offset = new Vector2(0, 0)
  1694. this.repeat = new Vector2(1, 1)
  1695. this.center = new Vector2(0, 0)
  1696. this.rotation = 0
  1697. this.matrixAutoUpdate = true
  1698. this.matrix = new Matrix3()
  1699. this.generateMipmaps = true
  1700. this.premultiplyAlpha = false
  1701. this.flipY = true
  1702. this.unpackAlignment = 4 // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
  1703. // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
  1704. //
  1705. // Also changing the encoding after already used by a Material will not automatically make the Material
  1706. // update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
  1707. this.encoding = encoding
  1708. this.userData = {}
  1709. this.version = 0
  1710. this.onUpdate = null
  1711. this.isRenderTargetTexture = false // indicates whether a texture belongs to a render target or not
  1712. this.needsPMREMUpdate = false // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
  1713. }
  1714. get image() {
  1715. return this.source.data
  1716. }
  1717. set image(value) {
  1718. this.source.data = value
  1719. }
  1720. updateMatrix() {
  1721. this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y)
  1722. }
  1723. clone() {
  1724. return new this.constructor().copy(this)
  1725. }
  1726. copy(source) {
  1727. this.name = source.name
  1728. this.source = source.source
  1729. this.mipmaps = source.mipmaps.slice(0)
  1730. this.mapping = source.mapping
  1731. this.wrapS = source.wrapS
  1732. this.wrapT = source.wrapT
  1733. this.magFilter = source.magFilter
  1734. this.minFilter = source.minFilter
  1735. this.anisotropy = source.anisotropy
  1736. this.format = source.format
  1737. this.internalFormat = source.internalFormat
  1738. this.type = source.type
  1739. this.offset.copy(source.offset)
  1740. this.repeat.copy(source.repeat)
  1741. this.center.copy(source.center)
  1742. this.rotation = source.rotation
  1743. this.matrixAutoUpdate = source.matrixAutoUpdate
  1744. this.matrix.copy(source.matrix)
  1745. this.generateMipmaps = source.generateMipmaps
  1746. this.premultiplyAlpha = source.premultiplyAlpha
  1747. this.flipY = source.flipY
  1748. this.unpackAlignment = source.unpackAlignment
  1749. this.encoding = source.encoding
  1750. this.userData = JSON.parse(JSON.stringify(source.userData))
  1751. this.needsUpdate = true
  1752. return this
  1753. }
  1754. toJSON(meta) {
  1755. const isRootObject = meta === undefined || typeof meta === 'string'
  1756. if (!isRootObject && meta.textures[this.uuid] !== undefined) {
  1757. return meta.textures[this.uuid]
  1758. }
  1759. const output = {
  1760. metadata: {
  1761. version: 4.5,
  1762. type: 'Texture',
  1763. generator: 'Texture.toJSON'
  1764. },
  1765. uuid: this.uuid,
  1766. name: this.name,
  1767. image: this.source.toJSON(meta).uuid,
  1768. mapping: this.mapping,
  1769. repeat: [this.repeat.x, this.repeat.y],
  1770. offset: [this.offset.x, this.offset.y],
  1771. center: [this.center.x, this.center.y],
  1772. rotation: this.rotation,
  1773. wrap: [this.wrapS, this.wrapT],
  1774. format: this.format,
  1775. type: this.type,
  1776. encoding: this.encoding,
  1777. minFilter: this.minFilter,
  1778. magFilter: this.magFilter,
  1779. anisotropy: this.anisotropy,
  1780. flipY: this.flipY,
  1781. premultiplyAlpha: this.premultiplyAlpha,
  1782. unpackAlignment: this.unpackAlignment
  1783. }
  1784. if (JSON.stringify(this.userData) !== '{}') output.userData = this.userData
  1785. if (!isRootObject) {
  1786. meta.textures[this.uuid] = output
  1787. }
  1788. return output
  1789. }
  1790. dispose() {
  1791. this.dispatchEvent({ type: 'dispose' })
  1792. }
  1793. transformUv(uv) {
  1794. if (this.mapping !== UVMapping) return uv
  1795. uv.applyMatrix3(this.matrix)
  1796. if (uv.x < 0 || uv.x > 1) {
  1797. switch (this.wrapS) {
  1798. case RepeatWrapping:
  1799. uv.x = uv.x - Math.floor(uv.x)
  1800. break
  1801. case ClampToEdgeWrapping:
  1802. uv.x = uv.x < 0 ? 0 : 1
  1803. break
  1804. case MirroredRepeatWrapping:
  1805. if (Math.abs(Math.floor(uv.x) % 2) === 1) {
  1806. uv.x = Math.ceil(uv.x) - uv.x
  1807. } else {
  1808. uv.x = uv.x - Math.floor(uv.x)
  1809. }
  1810. break
  1811. }
  1812. }
  1813. if (uv.y < 0 || uv.y > 1) {
  1814. switch (this.wrapT) {
  1815. case RepeatWrapping:
  1816. uv.y = uv.y - Math.floor(uv.y)
  1817. break
  1818. case ClampToEdgeWrapping:
  1819. uv.y = uv.y < 0 ? 0 : 1
  1820. break
  1821. case MirroredRepeatWrapping:
  1822. if (Math.abs(Math.floor(uv.y) % 2) === 1) {
  1823. uv.y = Math.ceil(uv.y) - uv.y
  1824. } else {
  1825. uv.y = uv.y - Math.floor(uv.y)
  1826. }
  1827. break
  1828. }
  1829. }
  1830. if (this.flipY) {
  1831. uv.y = 1 - uv.y
  1832. }
  1833. return uv
  1834. }
  1835. set needsUpdate(value) {
  1836. if (value === true) {
  1837. this.version++
  1838. this.source.needsUpdate = true
  1839. }
  1840. }
  1841. }
  1842. Texture.DEFAULT_IMAGE = null
  1843. Texture.DEFAULT_MAPPING = UVMapping
  1844. class Vector4 {
  1845. constructor(x = 0, y = 0, z = 0, w = 1) {
  1846. this.isVector4 = true
  1847. this.x = x
  1848. this.y = y
  1849. this.z = z
  1850. this.w = w
  1851. }
  1852. get width() {
  1853. return this.z
  1854. }
  1855. set width(value) {
  1856. this.z = value
  1857. }
  1858. get height() {
  1859. return this.w
  1860. }
  1861. set height(value) {
  1862. this.w = value
  1863. }
  1864. set(x, y, z, w) {
  1865. this.x = x
  1866. this.y = y
  1867. this.z = z
  1868. this.w = w
  1869. return this
  1870. }
  1871. setScalar(scalar) {
  1872. this.x = scalar
  1873. this.y = scalar
  1874. this.z = scalar
  1875. this.w = scalar
  1876. return this
  1877. }
  1878. setX(x) {
  1879. this.x = x
  1880. return this
  1881. }
  1882. setY(y) {
  1883. this.y = y
  1884. return this
  1885. }
  1886. setZ(z) {
  1887. this.z = z
  1888. return this
  1889. }
  1890. setW(w) {
  1891. this.w = w
  1892. return this
  1893. }
  1894. setComponent(index, value) {
  1895. switch (index) {
  1896. case 0:
  1897. this.x = value
  1898. break
  1899. case 1:
  1900. this.y = value
  1901. break
  1902. case 2:
  1903. this.z = value
  1904. break
  1905. case 3:
  1906. this.w = value
  1907. break
  1908. default:
  1909. throw new Error('index is out of range: ' + index)
  1910. }
  1911. return this
  1912. }
  1913. getComponent(index) {
  1914. switch (index) {
  1915. case 0:
  1916. return this.x
  1917. case 1:
  1918. return this.y
  1919. case 2:
  1920. return this.z
  1921. case 3:
  1922. return this.w
  1923. default:
  1924. throw new Error('index is out of range: ' + index)
  1925. }
  1926. }
  1927. clone() {
  1928. return new this.constructor(this.x, this.y, this.z, this.w)
  1929. }
  1930. copy(v) {
  1931. this.x = v.x
  1932. this.y = v.y
  1933. this.z = v.z
  1934. this.w = v.w !== undefined ? v.w : 1
  1935. return this
  1936. }
  1937. add(v, w) {
  1938. if (w !== undefined) {
  1939. console.warn('THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.')
  1940. return this.addVectors(v, w)
  1941. }
  1942. this.x += v.x
  1943. this.y += v.y
  1944. this.z += v.z
  1945. this.w += v.w
  1946. return this
  1947. }
  1948. addScalar(s) {
  1949. this.x += s
  1950. this.y += s
  1951. this.z += s
  1952. this.w += s
  1953. return this
  1954. }
  1955. addVectors(a, b) {
  1956. this.x = a.x + b.x
  1957. this.y = a.y + b.y
  1958. this.z = a.z + b.z
  1959. this.w = a.w + b.w
  1960. return this
  1961. }
  1962. addScaledVector(v, s) {
  1963. this.x += v.x * s
  1964. this.y += v.y * s
  1965. this.z += v.z * s
  1966. this.w += v.w * s
  1967. return this
  1968. }
  1969. sub(v, w) {
  1970. if (w !== undefined) {
  1971. console.warn('THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.')
  1972. return this.subVectors(v, w)
  1973. }
  1974. this.x -= v.x
  1975. this.y -= v.y
  1976. this.z -= v.z
  1977. this.w -= v.w
  1978. return this
  1979. }
  1980. subScalar(s) {
  1981. this.x -= s
  1982. this.y -= s
  1983. this.z -= s
  1984. this.w -= s
  1985. return this
  1986. }
  1987. subVectors(a, b) {
  1988. this.x = a.x - b.x
  1989. this.y = a.y - b.y
  1990. this.z = a.z - b.z
  1991. this.w = a.w - b.w
  1992. return this
  1993. }
  1994. multiply(v) {
  1995. this.x *= v.x
  1996. this.y *= v.y
  1997. this.z *= v.z
  1998. this.w *= v.w
  1999. return this
  2000. }
  2001. multiplyScalar(scalar) {
  2002. this.x *= scalar
  2003. this.y *= scalar
  2004. this.z *= scalar
  2005. this.w *= scalar
  2006. return this
  2007. }
  2008. applyMatrix4(m) {
  2009. const x = this.x,
  2010. y = this.y,
  2011. z = this.z,
  2012. w = this.w
  2013. const e = m.elements
  2014. this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w
  2015. this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w
  2016. this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w
  2017. this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w
  2018. return this
  2019. }
  2020. divideScalar(scalar) {
  2021. return this.multiplyScalar(1 / scalar)
  2022. }
  2023. setAxisAngleFromQuaternion(q) {
  2024. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
  2025. // q is assumed to be normalized
  2026. this.w = 2 * Math.acos(q.w)
  2027. const s = Math.sqrt(1 - q.w * q.w)
  2028. if (s < 0.0001) {
  2029. this.x = 1
  2030. this.y = 0
  2031. this.z = 0
  2032. } else {
  2033. this.x = q.x / s
  2034. this.y = q.y / s
  2035. this.z = q.z / s
  2036. }
  2037. return this
  2038. }
  2039. setAxisAngleFromRotationMatrix(m) {
  2040. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
  2041. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  2042. let angle, x, y, z // variables for result
  2043. const epsilon = 0.01, // margin to allow for rounding errors
  2044. epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
  2045. te = m.elements,
  2046. m11 = te[0],
  2047. m12 = te[4],
  2048. m13 = te[8],
  2049. m21 = te[1],
  2050. m22 = te[5],
  2051. m23 = te[9],
  2052. m31 = te[2],
  2053. m32 = te[6],
  2054. m33 = te[10]
  2055. if (Math.abs(m12 - m21) < epsilon && Math.abs(m13 - m31) < epsilon && Math.abs(m23 - m32) < epsilon) {
  2056. // singularity found
  2057. // first check for identity matrix which must have +1 for all terms
  2058. // in leading diagonal and zero in other terms
  2059. if (Math.abs(m12 + m21) < epsilon2 && Math.abs(m13 + m31) < epsilon2 && Math.abs(m23 + m32) < epsilon2 && Math.abs(m11 + m22 + m33 - 3) < epsilon2) {
  2060. // this singularity is identity matrix so angle = 0
  2061. this.set(1, 0, 0, 0)
  2062. return this // zero angle, arbitrary axis
  2063. }
  2064. // otherwise this singularity is angle = 180
  2065. angle = Math.PI
  2066. const xx = (m11 + 1) / 2
  2067. const yy = (m22 + 1) / 2
  2068. const zz = (m33 + 1) / 2
  2069. const xy = (m12 + m21) / 4
  2070. const xz = (m13 + m31) / 4
  2071. const yz = (m23 + m32) / 4
  2072. if (xx > yy && xx > zz) {
  2073. // m11 is the largest diagonal term
  2074. if (xx < epsilon) {
  2075. x = 0
  2076. y = 0.707106781
  2077. z = 0.707106781
  2078. } else {
  2079. x = Math.sqrt(xx)
  2080. y = xy / x
  2081. z = xz / x
  2082. }
  2083. } else if (yy > zz) {
  2084. // m22 is the largest diagonal term
  2085. if (yy < epsilon) {
  2086. x = 0.707106781
  2087. y = 0
  2088. z = 0.707106781
  2089. } else {
  2090. y = Math.sqrt(yy)
  2091. x = xy / y
  2092. z = yz / y
  2093. }
  2094. } else {
  2095. // m33 is the largest diagonal term so base result on this
  2096. if (zz < epsilon) {
  2097. x = 0.707106781
  2098. y = 0.707106781
  2099. z = 0
  2100. } else {
  2101. z = Math.sqrt(zz)
  2102. x = xz / z
  2103. y = yz / z
  2104. }
  2105. }
  2106. this.set(x, y, z, angle)
  2107. return this // return 180 deg rotation
  2108. }
  2109. // as we have reached here there are no singularities so we can handle normally
  2110. let s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12)) // used to normalize
  2111. if (Math.abs(s) < 0.001) s = 1
  2112. // prevent divide by zero, should not happen if matrix is orthogonal and should be
  2113. // caught by singularity test above, but I've left it in just in case
  2114. this.x = (m32 - m23) / s
  2115. this.y = (m13 - m31) / s
  2116. this.z = (m21 - m12) / s
  2117. this.w = Math.acos((m11 + m22 + m33 - 1) / 2)
  2118. return this
  2119. }
  2120. min(v) {
  2121. this.x = Math.min(this.x, v.x)
  2122. this.y = Math.min(this.y, v.y)
  2123. this.z = Math.min(this.z, v.z)
  2124. this.w = Math.min(this.w, v.w)
  2125. return this
  2126. }
  2127. max(v) {
  2128. this.x = Math.max(this.x, v.x)
  2129. this.y = Math.max(this.y, v.y)
  2130. this.z = Math.max(this.z, v.z)
  2131. this.w = Math.max(this.w, v.w)
  2132. return this
  2133. }
  2134. clamp(min, max) {
  2135. // assumes min < max, componentwise
  2136. this.x = Math.max(min.x, Math.min(max.x, this.x))
  2137. this.y = Math.max(min.y, Math.min(max.y, this.y))
  2138. this.z = Math.max(min.z, Math.min(max.z, this.z))
  2139. this.w = Math.max(min.w, Math.min(max.w, this.w))
  2140. return this
  2141. }
  2142. clampScalar(minVal, maxVal) {
  2143. this.x = Math.max(minVal, Math.min(maxVal, this.x))
  2144. this.y = Math.max(minVal, Math.min(maxVal, this.y))
  2145. this.z = Math.max(minVal, Math.min(maxVal, this.z))
  2146. this.w = Math.max(minVal, Math.min(maxVal, this.w))
  2147. return this
  2148. }
  2149. clampLength(min, max) {
  2150. const length = this.length()
  2151. return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)))
  2152. }
  2153. floor() {
  2154. this.x = Math.floor(this.x)
  2155. this.y = Math.floor(this.y)
  2156. this.z = Math.floor(this.z)
  2157. this.w = Math.floor(this.w)
  2158. return this
  2159. }
  2160. ceil() {
  2161. this.x = Math.ceil(this.x)
  2162. this.y = Math.ceil(this.y)
  2163. this.z = Math.ceil(this.z)
  2164. this.w = Math.ceil(this.w)
  2165. return this
  2166. }
  2167. round() {
  2168. this.x = Math.round(this.x)
  2169. this.y = Math.round(this.y)
  2170. this.z = Math.round(this.z)
  2171. this.w = Math.round(this.w)
  2172. return this
  2173. }
  2174. roundToZero() {
  2175. this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x)
  2176. this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y)
  2177. this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z)
  2178. this.w = this.w < 0 ? Math.ceil(this.w) : Math.floor(this.w)
  2179. return this
  2180. }
  2181. negate() {
  2182. this.x = -this.x
  2183. this.y = -this.y
  2184. this.z = -this.z
  2185. this.w = -this.w
  2186. return this
  2187. }
  2188. dot(v) {
  2189. return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w
  2190. }
  2191. lengthSq() {
  2192. return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w
  2193. }
  2194. length() {
  2195. return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)
  2196. }
  2197. manhattanLength() {
  2198. return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w)
  2199. }
  2200. normalize() {
  2201. return this.divideScalar(this.length() || 1)
  2202. }
  2203. setLength(length) {
  2204. return this.normalize().multiplyScalar(length)
  2205. }
  2206. lerp(v, alpha) {
  2207. this.x += (v.x - this.x) * alpha
  2208. this.y += (v.y - this.y) * alpha
  2209. this.z += (v.z - this.z) * alpha
  2210. this.w += (v.w - this.w) * alpha
  2211. return this
  2212. }
  2213. lerpVectors(v1, v2, alpha) {
  2214. this.x = v1.x + (v2.x - v1.x) * alpha
  2215. this.y = v1.y + (v2.y - v1.y) * alpha
  2216. this.z = v1.z + (v2.z - v1.z) * alpha
  2217. this.w = v1.w + (v2.w - v1.w) * alpha
  2218. return this
  2219. }
  2220. equals(v) {
  2221. return v.x === this.x && v.y === this.y && v.z === this.z && v.w === this.w
  2222. }
  2223. fromArray(array, offset = 0) {
  2224. this.x = array[offset]
  2225. this.y = array[offset + 1]
  2226. this.z = array[offset + 2]
  2227. this.w = array[offset + 3]
  2228. return this
  2229. }
  2230. toArray(array = [], offset = 0) {
  2231. array[offset] = this.x
  2232. array[offset + 1] = this.y
  2233. array[offset + 2] = this.z
  2234. array[offset + 3] = this.w
  2235. return array
  2236. }
  2237. fromBufferAttribute(attribute, index, offset) {
  2238. if (offset !== undefined) {
  2239. console.warn('THREE.Vector4: offset has been removed from .fromBufferAttribute().')
  2240. }
  2241. this.x = attribute.getX(index)
  2242. this.y = attribute.getY(index)
  2243. this.z = attribute.getZ(index)
  2244. this.w = attribute.getW(index)
  2245. return this
  2246. }
  2247. random() {
  2248. this.x = Math.random()
  2249. this.y = Math.random()
  2250. this.z = Math.random()
  2251. this.w = Math.random()
  2252. return this
  2253. }
  2254. *[Symbol.iterator]() {
  2255. yield this.x
  2256. yield this.y
  2257. yield this.z
  2258. yield this.w
  2259. }
  2260. }
  2261. /*
  2262. In options, we can specify:
  2263. * Texture parameters for an auto-generated target texture
  2264. * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
  2265. */
  2266. class WebGLRenderTarget extends EventDispatcher {
  2267. constructor(width, height, options = {}) {
  2268. super()
  2269. this.isWebGLRenderTarget = true
  2270. this.width = width
  2271. this.height = height
  2272. this.depth = 1
  2273. this.scissor = new Vector4(0, 0, width, height)
  2274. this.scissorTest = false
  2275. this.viewport = new Vector4(0, 0, width, height)
  2276. const image = { width: width, height: height, depth: 1 }
  2277. this.texture = new Texture(image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding)
  2278. this.texture.isRenderTargetTexture = true
  2279. this.texture.flipY = false
  2280. this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false
  2281. this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null
  2282. this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter
  2283. this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true
  2284. this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false
  2285. this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null
  2286. this.samples = options.samples !== undefined ? options.samples : 0
  2287. }
  2288. setSize(width, height, depth = 1) {
  2289. if (this.width !== width || this.height !== height || this.depth !== depth) {
  2290. this.width = width
  2291. this.height = height
  2292. this.depth = depth
  2293. this.texture.image.width = width
  2294. this.texture.image.height = height
  2295. this.texture.image.depth = depth
  2296. this.dispose()
  2297. }
  2298. this.viewport.set(0, 0, width, height)
  2299. this.scissor.set(0, 0, width, height)
  2300. }
  2301. clone() {
  2302. return new this.constructor().copy(this)
  2303. }
  2304. copy(source) {
  2305. this.width = source.width
  2306. this.height = source.height
  2307. this.depth = source.depth
  2308. this.viewport.copy(source.viewport)
  2309. this.texture = source.texture.clone()
  2310. this.texture.isRenderTargetTexture = true
  2311. // ensure image object is not shared, see #20328
  2312. const image = Object.assign({}, source.texture.image)
  2313. this.texture.source = new Source(image)
  2314. this.depthBuffer = source.depthBuffer
  2315. this.stencilBuffer = source.stencilBuffer
  2316. if (source.depthTexture !== null) this.depthTexture = source.depthTexture.clone()
  2317. this.samples = source.samples
  2318. return this
  2319. }
  2320. dispose() {
  2321. this.dispatchEvent({ type: 'dispose' })
  2322. }
  2323. }
  2324. class DataArrayTexture extends Texture {
  2325. constructor(data = null, width = 1, height = 1, depth = 1) {
  2326. super(null)
  2327. this.isDataArrayTexture = true
  2328. this.image = { data, width, height, depth }
  2329. this.magFilter = NearestFilter
  2330. this.minFilter = NearestFilter
  2331. this.wrapR = ClampToEdgeWrapping
  2332. this.generateMipmaps = false
  2333. this.flipY = false
  2334. this.unpackAlignment = 1
  2335. }
  2336. }
  2337. class WebGLArrayRenderTarget extends WebGLRenderTarget {
  2338. constructor(width, height, depth) {
  2339. super(width, height)
  2340. this.isWebGLArrayRenderTarget = true
  2341. this.depth = depth
  2342. this.texture = new DataArrayTexture(null, width, height, depth)
  2343. this.texture.isRenderTargetTexture = true
  2344. }
  2345. }
  2346. class Data3DTexture extends Texture {
  2347. constructor(data = null, width = 1, height = 1, depth = 1) {
  2348. // We're going to add .setXXX() methods for setting properties later.
  2349. // Users can still set in DataTexture3D directly.
  2350. //
  2351. // const texture = new THREE.DataTexture3D( data, width, height, depth );
  2352. // texture.anisotropy = 16;
  2353. //
  2354. // See #14839
  2355. super(null)
  2356. this.isData3DTexture = true
  2357. this.image = { data, width, height, depth }
  2358. this.magFilter = NearestFilter
  2359. this.minFilter = NearestFilter
  2360. this.wrapR = ClampToEdgeWrapping
  2361. this.generateMipmaps = false
  2362. this.flipY = false
  2363. this.unpackAlignment = 1
  2364. }
  2365. }
  2366. class WebGL3DRenderTarget extends WebGLRenderTarget {
  2367. constructor(width, height, depth) {
  2368. super(width, height)
  2369. this.isWebGL3DRenderTarget = true
  2370. this.depth = depth
  2371. this.texture = new Data3DTexture(null, width, height, depth)
  2372. this.texture.isRenderTargetTexture = true
  2373. }
  2374. }
  2375. class WebGLMultipleRenderTargets extends WebGLRenderTarget {
  2376. constructor(width, height, count, options = {}) {
  2377. super(width, height, options)
  2378. this.isWebGLMultipleRenderTargets = true
  2379. const texture = this.texture
  2380. this.texture = []
  2381. for (let i = 0; i < count; i++) {
  2382. this.texture[i] = texture.clone()
  2383. this.texture[i].isRenderTargetTexture = true
  2384. }
  2385. }
  2386. setSize(width, height, depth = 1) {
  2387. if (this.width !== width || this.height !== height || this.depth !== depth) {
  2388. this.width = width
  2389. this.height = height
  2390. this.depth = depth
  2391. for (let i = 0, il = this.texture.length; i < il; i++) {
  2392. this.texture[i].image.width = width
  2393. this.texture[i].image.height = height
  2394. this.texture[i].image.depth = depth
  2395. }
  2396. this.dispose()
  2397. }
  2398. this.viewport.set(0, 0, width, height)
  2399. this.scissor.set(0, 0, width, height)
  2400. return this
  2401. }
  2402. copy(source) {
  2403. this.dispose()
  2404. this.width = source.width
  2405. this.height = source.height
  2406. this.depth = source.depth
  2407. this.viewport.set(0, 0, this.width, this.height)
  2408. this.scissor.set(0, 0, this.width, this.height)
  2409. this.depthBuffer = source.depthBuffer
  2410. this.stencilBuffer = source.stencilBuffer
  2411. if (source.depthTexture !== null) this.depthTexture = source.depthTexture.clone()
  2412. this.texture.length = 0
  2413. for (let i = 0, il = source.texture.length; i < il; i++) {
  2414. this.texture[i] = source.texture[i].clone()
  2415. this.texture[i].isRenderTargetTexture = true
  2416. }
  2417. return this
  2418. }
  2419. }
  2420. class Quaternion {
  2421. constructor(x = 0, y = 0, z = 0, w = 1) {
  2422. this.isQuaternion = true
  2423. this._x = x
  2424. this._y = y
  2425. this._z = z
  2426. this._w = w
  2427. }
  2428. static slerp(qa, qb, qm, t) {
  2429. console.warn('THREE.Quaternion: Static .slerp() has been deprecated. Use qm.slerpQuaternions( qa, qb, t ) instead.')
  2430. return qm.slerpQuaternions(qa, qb, t)
  2431. }
  2432. static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {
  2433. // fuzz-free, array-based Quaternion SLERP operation
  2434. let x0 = src0[srcOffset0 + 0],
  2435. y0 = src0[srcOffset0 + 1],
  2436. z0 = src0[srcOffset0 + 2],
  2437. w0 = src0[srcOffset0 + 3]
  2438. const x1 = src1[srcOffset1 + 0],
  2439. y1 = src1[srcOffset1 + 1],
  2440. z1 = src1[srcOffset1 + 2],
  2441. w1 = src1[srcOffset1 + 3]
  2442. if (t === 0) {
  2443. dst[dstOffset + 0] = x0
  2444. dst[dstOffset + 1] = y0
  2445. dst[dstOffset + 2] = z0
  2446. dst[dstOffset + 3] = w0
  2447. return
  2448. }
  2449. if (t === 1) {
  2450. dst[dstOffset + 0] = x1
  2451. dst[dstOffset + 1] = y1
  2452. dst[dstOffset + 2] = z1
  2453. dst[dstOffset + 3] = w1
  2454. return
  2455. }
  2456. if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
  2457. let s = 1 - t
  2458. const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
  2459. dir = cos >= 0 ? 1 : -1,
  2460. sqrSin = 1 - cos * cos
  2461. // Skip the Slerp for tiny steps to avoid numeric problems:
  2462. if (sqrSin > Number.EPSILON) {
  2463. const sin = Math.sqrt(sqrSin),
  2464. len = Math.atan2(sin, cos * dir)
  2465. s = Math.sin(s * len) / sin
  2466. t = Math.sin(t * len) / sin
  2467. }
  2468. const tDir = t * dir
  2469. x0 = x0 * s + x1 * tDir
  2470. y0 = y0 * s + y1 * tDir
  2471. z0 = z0 * s + z1 * tDir
  2472. w0 = w0 * s + w1 * tDir
  2473. // Normalize in case we just did a lerp:
  2474. if (s === 1 - t) {
  2475. const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0)
  2476. x0 *= f
  2477. y0 *= f
  2478. z0 *= f
  2479. w0 *= f
  2480. }
  2481. }
  2482. dst[dstOffset] = x0
  2483. dst[dstOffset + 1] = y0
  2484. dst[dstOffset + 2] = z0
  2485. dst[dstOffset + 3] = w0
  2486. }
  2487. static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) {
  2488. const x0 = src0[srcOffset0]
  2489. const y0 = src0[srcOffset0 + 1]
  2490. const z0 = src0[srcOffset0 + 2]
  2491. const w0 = src0[srcOffset0 + 3]
  2492. const x1 = src1[srcOffset1]
  2493. const y1 = src1[srcOffset1 + 1]
  2494. const z1 = src1[srcOffset1 + 2]
  2495. const w1 = src1[srcOffset1 + 3]
  2496. dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1
  2497. dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1
  2498. dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1
  2499. dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1
  2500. return dst
  2501. }
  2502. get x() {
  2503. return this._x
  2504. }
  2505. set x(value) {
  2506. this._x = value
  2507. this._onChangeCallback()
  2508. }
  2509. get y() {
  2510. return this._y
  2511. }
  2512. set y(value) {
  2513. this._y = value
  2514. this._onChangeCallback()
  2515. }
  2516. get z() {
  2517. return this._z
  2518. }
  2519. set z(value) {
  2520. this._z = value
  2521. this._onChangeCallback()
  2522. }
  2523. get w() {
  2524. return this._w
  2525. }
  2526. set w(value) {
  2527. this._w = value
  2528. this._onChangeCallback()
  2529. }
  2530. set(x, y, z, w) {
  2531. this._x = x
  2532. this._y = y
  2533. this._z = z
  2534. this._w = w
  2535. this._onChangeCallback()
  2536. return this
  2537. }
  2538. clone() {
  2539. return new this.constructor(this._x, this._y, this._z, this._w)
  2540. }
  2541. copy(quaternion) {
  2542. this._x = quaternion.x
  2543. this._y = quaternion.y
  2544. this._z = quaternion.z
  2545. this._w = quaternion.w
  2546. this._onChangeCallback()
  2547. return this
  2548. }
  2549. setFromEuler(euler, update) {
  2550. if (!(euler && euler.isEuler)) {
  2551. throw new Error('THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.')
  2552. }
  2553. const x = euler._x,
  2554. y = euler._y,
  2555. z = euler._z,
  2556. order = euler._order
  2557. // http://www.mathworks.com/matlabcentral/fileexchange/
  2558. // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
  2559. // content/SpinCalc.m
  2560. const cos = Math.cos
  2561. const sin = Math.sin
  2562. const c1 = cos(x / 2)
  2563. const c2 = cos(y / 2)
  2564. const c3 = cos(z / 2)
  2565. const s1 = sin(x / 2)
  2566. const s2 = sin(y / 2)
  2567. const s3 = sin(z / 2)
  2568. switch (order) {
  2569. case 'XYZ':
  2570. this._x = s1 * c2 * c3 + c1 * s2 * s3
  2571. this._y = c1 * s2 * c3 - s1 * c2 * s3
  2572. this._z = c1 * c2 * s3 + s1 * s2 * c3
  2573. this._w = c1 * c2 * c3 - s1 * s2 * s3
  2574. break
  2575. case 'YXZ':
  2576. this._x = s1 * c2 * c3 + c1 * s2 * s3
  2577. this._y = c1 * s2 * c3 - s1 * c2 * s3
  2578. this._z = c1 * c2 * s3 - s1 * s2 * c3
  2579. this._w = c1 * c2 * c3 + s1 * s2 * s3
  2580. break
  2581. case 'ZXY':
  2582. this._x = s1 * c2 * c3 - c1 * s2 * s3
  2583. this._y = c1 * s2 * c3 + s1 * c2 * s3
  2584. this._z = c1 * c2 * s3 + s1 * s2 * c3
  2585. this._w = c1 * c2 * c3 - s1 * s2 * s3
  2586. break
  2587. case 'ZYX':
  2588. this._x = s1 * c2 * c3 - c1 * s2 * s3
  2589. this._y = c1 * s2 * c3 + s1 * c2 * s3
  2590. this._z = c1 * c2 * s3 - s1 * s2 * c3
  2591. this._w = c1 * c2 * c3 + s1 * s2 * s3
  2592. break
  2593. case 'YZX':
  2594. this._x = s1 * c2 * c3 + c1 * s2 * s3
  2595. this._y = c1 * s2 * c3 + s1 * c2 * s3
  2596. this._z = c1 * c2 * s3 - s1 * s2 * c3
  2597. this._w = c1 * c2 * c3 - s1 * s2 * s3
  2598. break
  2599. case 'XZY':
  2600. this._x = s1 * c2 * c3 - c1 * s2 * s3
  2601. this._y = c1 * s2 * c3 - s1 * c2 * s3
  2602. this._z = c1 * c2 * s3 + s1 * s2 * c3
  2603. this._w = c1 * c2 * c3 + s1 * s2 * s3
  2604. break
  2605. default:
  2606. console.warn('THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order)
  2607. }
  2608. if (update !== false) this._onChangeCallback()
  2609. return this
  2610. }
  2611. setFromAxisAngle(axis, angle) {
  2612. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
  2613. // assumes axis is normalized
  2614. const halfAngle = angle / 2,
  2615. s = Math.sin(halfAngle)
  2616. this._x = axis.x * s
  2617. this._y = axis.y * s
  2618. this._z = axis.z * s
  2619. this._w = Math.cos(halfAngle)
  2620. this._onChangeCallback()
  2621. return this
  2622. }
  2623. setFromRotationMatrix(m) {
  2624. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  2625. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  2626. const te = m.elements,
  2627. m11 = te[0],
  2628. m12 = te[4],
  2629. m13 = te[8],
  2630. m21 = te[1],
  2631. m22 = te[5],
  2632. m23 = te[9],
  2633. m31 = te[2],
  2634. m32 = te[6],
  2635. m33 = te[10],
  2636. trace = m11 + m22 + m33
  2637. if (trace > 0) {
  2638. const s = 0.5 / Math.sqrt(trace + 1.0)
  2639. this._w = 0.25 / s
  2640. this._x = (m32 - m23) * s
  2641. this._y = (m13 - m31) * s
  2642. this._z = (m21 - m12) * s
  2643. } else if (m11 > m22 && m11 > m33) {
  2644. const s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33)
  2645. this._w = (m32 - m23) / s
  2646. this._x = 0.25 * s
  2647. this._y = (m12 + m21) / s
  2648. this._z = (m13 + m31) / s
  2649. } else if (m22 > m33) {
  2650. const s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33)
  2651. this._w = (m13 - m31) / s
  2652. this._x = (m12 + m21) / s
  2653. this._y = 0.25 * s
  2654. this._z = (m23 + m32) / s
  2655. } else {
  2656. const s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22)
  2657. this._w = (m21 - m12) / s
  2658. this._x = (m13 + m31) / s
  2659. this._y = (m23 + m32) / s
  2660. this._z = 0.25 * s
  2661. }
  2662. this._onChangeCallback()
  2663. return this
  2664. }
  2665. setFromUnitVectors(vFrom, vTo) {
  2666. // assumes direction vectors vFrom and vTo are normalized
  2667. let r = vFrom.dot(vTo) + 1
  2668. if (r < Number.EPSILON) {
  2669. // vFrom and vTo point in opposite directions
  2670. r = 0
  2671. if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
  2672. this._x = -vFrom.y
  2673. this._y = vFrom.x
  2674. this._z = 0
  2675. this._w = r
  2676. } else {
  2677. this._x = 0
  2678. this._y = -vFrom.z
  2679. this._z = vFrom.y
  2680. this._w = r
  2681. }
  2682. } else {
  2683. // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
  2684. this._x = vFrom.y * vTo.z - vFrom.z * vTo.y
  2685. this._y = vFrom.z * vTo.x - vFrom.x * vTo.z
  2686. this._z = vFrom.x * vTo.y - vFrom.y * vTo.x
  2687. this._w = r
  2688. }
  2689. return this.normalize()
  2690. }
  2691. angleTo(q) {
  2692. return 2 * Math.acos(Math.abs(clamp(this.dot(q), -1, 1)))
  2693. }
  2694. rotateTowards(q, step) {
  2695. const angle = this.angleTo(q)
  2696. if (angle === 0) return this
  2697. const t = Math.min(1, step / angle)
  2698. this.slerp(q, t)
  2699. return this
  2700. }
  2701. identity() {
  2702. return this.set(0, 0, 0, 1)
  2703. }
  2704. invert() {
  2705. // quaternion is assumed to have unit length
  2706. return this.conjugate()
  2707. }
  2708. conjugate() {
  2709. this._x *= -1
  2710. this._y *= -1
  2711. this._z *= -1
  2712. this._onChangeCallback()
  2713. return this
  2714. }
  2715. dot(v) {
  2716. return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w
  2717. }
  2718. lengthSq() {
  2719. return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w
  2720. }
  2721. length() {
  2722. return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w)
  2723. }
  2724. normalize() {
  2725. let l = this.length()
  2726. if (l === 0) {
  2727. this._x = 0
  2728. this._y = 0
  2729. this._z = 0
  2730. this._w = 1
  2731. } else {
  2732. l = 1 / l
  2733. this._x = this._x * l
  2734. this._y = this._y * l
  2735. this._z = this._z * l
  2736. this._w = this._w * l
  2737. }
  2738. this._onChangeCallback()
  2739. return this
  2740. }
  2741. multiply(q, p) {
  2742. if (p !== undefined) {
  2743. console.warn('THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.')
  2744. return this.multiplyQuaternions(q, p)
  2745. }
  2746. return this.multiplyQuaternions(this, q)
  2747. }
  2748. premultiply(q) {
  2749. return this.multiplyQuaternions(q, this)
  2750. }
  2751. multiplyQuaternions(a, b) {
  2752. // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
  2753. const qax = a._x,
  2754. qay = a._y,
  2755. qaz = a._z,
  2756. qaw = a._w
  2757. const qbx = b._x,
  2758. qby = b._y,
  2759. qbz = b._z,
  2760. qbw = b._w
  2761. this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby
  2762. this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz
  2763. this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx
  2764. this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz
  2765. this._onChangeCallback()
  2766. return this
  2767. }
  2768. slerp(qb, t) {
  2769. if (t === 0) return this
  2770. if (t === 1) return this.copy(qb)
  2771. const x = this._x,
  2772. y = this._y,
  2773. z = this._z,
  2774. w = this._w
  2775. // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
  2776. let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z
  2777. if (cosHalfTheta < 0) {
  2778. this._w = -qb._w
  2779. this._x = -qb._x
  2780. this._y = -qb._y
  2781. this._z = -qb._z
  2782. cosHalfTheta = -cosHalfTheta
  2783. } else {
  2784. this.copy(qb)
  2785. }
  2786. if (cosHalfTheta >= 1.0) {
  2787. this._w = w
  2788. this._x = x
  2789. this._y = y
  2790. this._z = z
  2791. return this
  2792. }
  2793. const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta
  2794. if (sqrSinHalfTheta <= Number.EPSILON) {
  2795. const s = 1 - t
  2796. this._w = s * w + t * this._w
  2797. this._x = s * x + t * this._x
  2798. this._y = s * y + t * this._y
  2799. this._z = s * z + t * this._z
  2800. this.normalize()
  2801. this._onChangeCallback()
  2802. return this
  2803. }
  2804. const sinHalfTheta = Math.sqrt(sqrSinHalfTheta)
  2805. const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta)
  2806. const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
  2807. ratioB = Math.sin(t * halfTheta) / sinHalfTheta
  2808. this._w = w * ratioA + this._w * ratioB
  2809. this._x = x * ratioA + this._x * ratioB
  2810. this._y = y * ratioA + this._y * ratioB
  2811. this._z = z * ratioA + this._z * ratioB
  2812. this._onChangeCallback()
  2813. return this
  2814. }
  2815. slerpQuaternions(qa, qb, t) {
  2816. return this.copy(qa).slerp(qb, t)
  2817. }
  2818. random() {
  2819. // Derived from http://planning.cs.uiuc.edu/node198.html
  2820. // Note, this source uses w, x, y, z ordering,
  2821. // so we swap the order below.
  2822. const u1 = Math.random()
  2823. const sqrt1u1 = Math.sqrt(1 - u1)
  2824. const sqrtu1 = Math.sqrt(u1)
  2825. const u2 = 2 * Math.PI * Math.random()
  2826. const u3 = 2 * Math.PI * Math.random()
  2827. return this.set(sqrt1u1 * Math.cos(u2), sqrtu1 * Math.sin(u3), sqrtu1 * Math.cos(u3), sqrt1u1 * Math.sin(u2))
  2828. }
  2829. equals(quaternion) {
  2830. return quaternion._x === this._x && quaternion._y === this._y && quaternion._z === this._z && quaternion._w === this._w
  2831. }
  2832. fromArray(array, offset = 0) {
  2833. this._x = array[offset]
  2834. this._y = array[offset + 1]
  2835. this._z = array[offset + 2]
  2836. this._w = array[offset + 3]
  2837. this._onChangeCallback()
  2838. return this
  2839. }
  2840. toArray(array = [], offset = 0) {
  2841. array[offset] = this._x
  2842. array[offset + 1] = this._y
  2843. array[offset + 2] = this._z
  2844. array[offset + 3] = this._w
  2845. return array
  2846. }
  2847. fromBufferAttribute(attribute, index) {
  2848. this._x = attribute.getX(index)
  2849. this._y = attribute.getY(index)
  2850. this._z = attribute.getZ(index)
  2851. this._w = attribute.getW(index)
  2852. return this
  2853. }
  2854. _onChange(callback) {
  2855. this._onChangeCallback = callback
  2856. return this
  2857. }
  2858. _onChangeCallback() {}
  2859. *[Symbol.iterator]() {
  2860. yield this._x
  2861. yield this._y
  2862. yield this._z
  2863. yield this._w
  2864. }
  2865. }
  2866. class Vector3 {
  2867. constructor(x = 0, y = 0, z = 0) {
  2868. this.isVector3 = true
  2869. this.x = x
  2870. this.y = y
  2871. this.z = z
  2872. }
  2873. set(x, y, z) {
  2874. if (z === undefined) z = this.z // sprite.scale.set(x,y)
  2875. this.x = x
  2876. this.y = y
  2877. this.z = z
  2878. return this
  2879. }
  2880. setScalar(scalar) {
  2881. this.x = scalar
  2882. this.y = scalar
  2883. this.z = scalar
  2884. return this
  2885. }
  2886. setX(x) {
  2887. this.x = x
  2888. return this
  2889. }
  2890. setY(y) {
  2891. this.y = y
  2892. return this
  2893. }
  2894. setZ(z) {
  2895. this.z = z
  2896. return this
  2897. }
  2898. setComponent(index, value) {
  2899. switch (index) {
  2900. case 0:
  2901. this.x = value
  2902. break
  2903. case 1:
  2904. this.y = value
  2905. break
  2906. case 2:
  2907. this.z = value
  2908. break
  2909. default:
  2910. throw new Error('index is out of range: ' + index)
  2911. }
  2912. return this
  2913. }
  2914. getComponent(index) {
  2915. switch (index) {
  2916. case 0:
  2917. return this.x
  2918. case 1:
  2919. return this.y
  2920. case 2:
  2921. return this.z
  2922. default:
  2923. throw new Error('index is out of range: ' + index)
  2924. }
  2925. }
  2926. clone() {
  2927. return new this.constructor(this.x, this.y, this.z)
  2928. }
  2929. copy(v) {
  2930. this.x = v.x
  2931. this.y = v.y
  2932. this.z = v.z
  2933. return this
  2934. }
  2935. add(v, w) {
  2936. if (w !== undefined) {
  2937. console.warn('THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.')
  2938. return this.addVectors(v, w)
  2939. }
  2940. this.x += v.x
  2941. this.y += v.y
  2942. this.z += v.z
  2943. return this
  2944. }
  2945. addScalar(s) {
  2946. this.x += s
  2947. this.y += s
  2948. this.z += s
  2949. return this
  2950. }
  2951. addVectors(a, b) {
  2952. this.x = a.x + b.x
  2953. this.y = a.y + b.y
  2954. this.z = a.z + b.z
  2955. return this
  2956. }
  2957. addScaledVector(v, s) {
  2958. this.x += v.x * s
  2959. this.y += v.y * s
  2960. this.z += v.z * s
  2961. return this
  2962. }
  2963. sub(v, w) {
  2964. if (w !== undefined) {
  2965. console.warn('THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.')
  2966. return this.subVectors(v, w)
  2967. }
  2968. this.x -= v.x
  2969. this.y -= v.y
  2970. this.z -= v.z
  2971. return this
  2972. }
  2973. subScalar(s) {
  2974. this.x -= s
  2975. this.y -= s
  2976. this.z -= s
  2977. return this
  2978. }
  2979. subVectors(a, b) {
  2980. this.x = a.x - b.x
  2981. this.y = a.y - b.y
  2982. this.z = a.z - b.z
  2983. return this
  2984. }
  2985. multiply(v, w) {
  2986. if (w !== undefined) {
  2987. console.warn('THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.')
  2988. return this.multiplyVectors(v, w)
  2989. }
  2990. this.x *= v.x
  2991. this.y *= v.y
  2992. this.z *= v.z
  2993. return this
  2994. }
  2995. multiplyScalar(scalar) {
  2996. this.x *= scalar
  2997. this.y *= scalar
  2998. this.z *= scalar
  2999. return this
  3000. }
  3001. multiplyVectors(a, b) {
  3002. this.x = a.x * b.x
  3003. this.y = a.y * b.y
  3004. this.z = a.z * b.z
  3005. return this
  3006. }
  3007. applyEuler(euler) {
  3008. if (!(euler && euler.isEuler)) {
  3009. console.error('THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.')
  3010. }
  3011. return this.applyQuaternion(_quaternion$4.setFromEuler(euler))
  3012. }
  3013. applyAxisAngle(axis, angle) {
  3014. return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle))
  3015. }
  3016. applyMatrix3(m) {
  3017. const x = this.x,
  3018. y = this.y,
  3019. z = this.z
  3020. const e = m.elements
  3021. this.x = e[0] * x + e[3] * y + e[6] * z
  3022. this.y = e[1] * x + e[4] * y + e[7] * z
  3023. this.z = e[2] * x + e[5] * y + e[8] * z
  3024. return this
  3025. }
  3026. applyNormalMatrix(m) {
  3027. return this.applyMatrix3(m).normalize()
  3028. }
  3029. applyMatrix4(m) {
  3030. const x = this.x,
  3031. y = this.y,
  3032. z = this.z
  3033. const e = m.elements
  3034. const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15])
  3035. this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w
  3036. this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w
  3037. this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w
  3038. return this
  3039. }
  3040. applyQuaternion(q) {
  3041. const x = this.x,
  3042. y = this.y,
  3043. z = this.z
  3044. const qx = q.x,
  3045. qy = q.y,
  3046. qz = q.z,
  3047. qw = q.w
  3048. // calculate quat * vector
  3049. const ix = qw * x + qy * z - qz * y
  3050. const iy = qw * y + qz * x - qx * z
  3051. const iz = qw * z + qx * y - qy * x
  3052. const iw = -qx * x - qy * y - qz * z
  3053. // calculate result * inverse quat
  3054. this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy
  3055. this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz
  3056. this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx
  3057. return this
  3058. }
  3059. project(camera) {
  3060. return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix)
  3061. }
  3062. unproject(camera) {
  3063. return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld)
  3064. }
  3065. transformDirection(m) {
  3066. // input: THREE.Matrix4 affine matrix
  3067. // vector interpreted as a direction
  3068. const x = this.x,
  3069. y = this.y,
  3070. z = this.z
  3071. const e = m.elements
  3072. this.x = e[0] * x + e[4] * y + e[8] * z
  3073. this.y = e[1] * x + e[5] * y + e[9] * z
  3074. this.z = e[2] * x + e[6] * y + e[10] * z
  3075. return this.normalize()
  3076. }
  3077. divide(v) {
  3078. this.x /= v.x
  3079. this.y /= v.y
  3080. this.z /= v.z
  3081. return this
  3082. }
  3083. divideScalar(scalar) {
  3084. return this.multiplyScalar(1 / scalar)
  3085. }
  3086. min(v) {
  3087. this.x = Math.min(this.x, v.x)
  3088. this.y = Math.min(this.y, v.y)
  3089. this.z = Math.min(this.z, v.z)
  3090. return this
  3091. }
  3092. max(v) {
  3093. this.x = Math.max(this.x, v.x)
  3094. this.y = Math.max(this.y, v.y)
  3095. this.z = Math.max(this.z, v.z)
  3096. return this
  3097. }
  3098. clamp(min, max) {
  3099. // assumes min < max, componentwise
  3100. this.x = Math.max(min.x, Math.min(max.x, this.x))
  3101. this.y = Math.max(min.y, Math.min(max.y, this.y))
  3102. this.z = Math.max(min.z, Math.min(max.z, this.z))
  3103. return this
  3104. }
  3105. clampScalar(minVal, maxVal) {
  3106. this.x = Math.max(minVal, Math.min(maxVal, this.x))
  3107. this.y = Math.max(minVal, Math.min(maxVal, this.y))
  3108. this.z = Math.max(minVal, Math.min(maxVal, this.z))
  3109. return this
  3110. }
  3111. clampLength(min, max) {
  3112. const length = this.length()
  3113. return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)))
  3114. }
  3115. floor() {
  3116. this.x = Math.floor(this.x)
  3117. this.y = Math.floor(this.y)
  3118. this.z = Math.floor(this.z)
  3119. return this
  3120. }
  3121. ceil() {
  3122. this.x = Math.ceil(this.x)
  3123. this.y = Math.ceil(this.y)
  3124. this.z = Math.ceil(this.z)
  3125. return this
  3126. }
  3127. round() {
  3128. this.x = Math.round(this.x)
  3129. this.y = Math.round(this.y)
  3130. this.z = Math.round(this.z)
  3131. return this
  3132. }
  3133. roundToZero() {
  3134. this.x = this.x < 0 ? Math.ceil(this.x) : Math.floor(this.x)
  3135. this.y = this.y < 0 ? Math.ceil(this.y) : Math.floor(this.y)
  3136. this.z = this.z < 0 ? Math.ceil(this.z) : Math.floor(this.z)
  3137. return this
  3138. }
  3139. negate() {
  3140. this.x = -this.x
  3141. this.y = -this.y
  3142. this.z = -this.z
  3143. return this
  3144. }
  3145. dot(v) {
  3146. return this.x * v.x + this.y * v.y + this.z * v.z
  3147. }
  3148. // TODO lengthSquared?
  3149. lengthSq() {
  3150. return this.x * this.x + this.y * this.y + this.z * this.z
  3151. }
  3152. length() {
  3153. return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z)
  3154. }
  3155. manhattanLength() {
  3156. return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z)
  3157. }
  3158. normalize() {
  3159. return this.divideScalar(this.length() || 1)
  3160. }
  3161. setLength(length) {
  3162. return this.normalize().multiplyScalar(length)
  3163. }
  3164. lerp(v, alpha) {
  3165. this.x += (v.x - this.x) * alpha
  3166. this.y += (v.y - this.y) * alpha
  3167. this.z += (v.z - this.z) * alpha
  3168. return this
  3169. }
  3170. lerpVectors(v1, v2, alpha) {
  3171. this.x = v1.x + (v2.x - v1.x) * alpha
  3172. this.y = v1.y + (v2.y - v1.y) * alpha
  3173. this.z = v1.z + (v2.z - v1.z) * alpha
  3174. return this
  3175. }
  3176. cross(v, w) {
  3177. if (w !== undefined) {
  3178. console.warn('THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.')
  3179. return this.crossVectors(v, w)
  3180. }
  3181. return this.crossVectors(this, v)
  3182. }
  3183. crossVectors(a, b) {
  3184. const ax = a.x,
  3185. ay = a.y,
  3186. az = a.z
  3187. const bx = b.x,
  3188. by = b.y,
  3189. bz = b.z
  3190. this.x = ay * bz - az * by
  3191. this.y = az * bx - ax * bz
  3192. this.z = ax * by - ay * bx
  3193. return this
  3194. }
  3195. projectOnVector(v) {
  3196. const denominator = v.lengthSq()
  3197. if (denominator === 0) return this.set(0, 0, 0)
  3198. const scalar = v.dot(this) / denominator
  3199. return this.copy(v).multiplyScalar(scalar)
  3200. }
  3201. projectOnPlane(planeNormal) {
  3202. _vector$c.copy(this).projectOnVector(planeNormal)
  3203. return this.sub(_vector$c)
  3204. }
  3205. reflect(normal) {
  3206. // reflect incident vector off plane orthogonal to normal
  3207. // normal is assumed to have unit length
  3208. return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)))
  3209. }
  3210. angleTo(v) {
  3211. const denominator = Math.sqrt(this.lengthSq() * v.lengthSq())
  3212. if (denominator === 0) return Math.PI / 2
  3213. const theta = this.dot(v) / denominator
  3214. // clamp, to handle numerical problems
  3215. return Math.acos(clamp(theta, -1, 1))
  3216. }
  3217. distanceTo(v) {
  3218. return Math.sqrt(this.distanceToSquared(v))
  3219. }
  3220. distanceToSquared(v) {
  3221. const dx = this.x - v.x,
  3222. dy = this.y - v.y,
  3223. dz = this.z - v.z
  3224. return dx * dx + dy * dy + dz * dz
  3225. }
  3226. manhattanDistanceTo(v) {
  3227. return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z)
  3228. }
  3229. setFromSpherical(s) {
  3230. return this.setFromSphericalCoords(s.radius, s.phi, s.theta)
  3231. }
  3232. setFromSphericalCoords(radius, phi, theta) {
  3233. const sinPhiRadius = Math.sin(phi) * radius
  3234. this.x = sinPhiRadius * Math.sin(theta)
  3235. this.y = Math.cos(phi) * radius
  3236. this.z = sinPhiRadius * Math.cos(theta)
  3237. return this
  3238. }
  3239. setFromCylindrical(c) {
  3240. return this.setFromCylindricalCoords(c.radius, c.theta, c.y)
  3241. }
  3242. setFromCylindricalCoords(radius, theta, y) {
  3243. this.x = radius * Math.sin(theta)
  3244. this.y = y
  3245. this.z = radius * Math.cos(theta)
  3246. return this
  3247. }
  3248. setFromMatrixPosition(m) {
  3249. const e = m.elements
  3250. this.x = e[12]
  3251. this.y = e[13]
  3252. this.z = e[14]
  3253. return this
  3254. }
  3255. setFromMatrixScale(m) {
  3256. const sx = this.setFromMatrixColumn(m, 0).length()
  3257. const sy = this.setFromMatrixColumn(m, 1).length()
  3258. const sz = this.setFromMatrixColumn(m, 2).length()
  3259. this.x = sx
  3260. this.y = sy
  3261. this.z = sz
  3262. return this
  3263. }
  3264. setFromMatrixColumn(m, index) {
  3265. return this.fromArray(m.elements, index * 4)
  3266. }
  3267. setFromMatrix3Column(m, index) {
  3268. return this.fromArray(m.elements, index * 3)
  3269. }
  3270. setFromEuler(e) {
  3271. this.x = e._x
  3272. this.y = e._y
  3273. this.z = e._z
  3274. return this
  3275. }
  3276. equals(v) {
  3277. return v.x === this.x && v.y === this.y && v.z === this.z
  3278. }
  3279. fromArray(array, offset = 0) {
  3280. this.x = array[offset]
  3281. this.y = array[offset + 1]
  3282. this.z = array[offset + 2]
  3283. return this
  3284. }
  3285. toArray(array = [], offset = 0) {
  3286. array[offset] = this.x
  3287. array[offset + 1] = this.y
  3288. array[offset + 2] = this.z
  3289. return array
  3290. }
  3291. fromBufferAttribute(attribute, index, offset) {
  3292. if (offset !== undefined) {
  3293. console.warn('THREE.Vector3: offset has been removed from .fromBufferAttribute().')
  3294. }
  3295. this.x = attribute.getX(index)
  3296. this.y = attribute.getY(index)
  3297. this.z = attribute.getZ(index)
  3298. return this
  3299. }
  3300. random() {
  3301. this.x = Math.random()
  3302. this.y = Math.random()
  3303. this.z = Math.random()
  3304. return this
  3305. }
  3306. randomDirection() {
  3307. // Derived from https://mathworld.wolfram.com/SpherePointPicking.html
  3308. const u = (Math.random() - 0.5) * 2
  3309. const t = Math.random() * Math.PI * 2
  3310. const f = Math.sqrt(1 - u ** 2)
  3311. this.x = f * Math.cos(t)
  3312. this.y = f * Math.sin(t)
  3313. this.z = u
  3314. return this
  3315. }
  3316. *[Symbol.iterator]() {
  3317. yield this.x
  3318. yield this.y
  3319. yield this.z
  3320. }
  3321. }
  3322. const _vector$c = /*@__PURE__*/ new Vector3()
  3323. const _quaternion$4 = /*@__PURE__*/ new Quaternion()
  3324. class Box3 {
  3325. constructor(min = new Vector3(+Infinity, +Infinity, +Infinity), max = new Vector3(-Infinity, -Infinity, -Infinity)) {
  3326. this.isBox3 = true
  3327. this.min = min
  3328. this.max = max
  3329. }
  3330. set(min, max) {
  3331. this.min.copy(min)
  3332. this.max.copy(max)
  3333. return this
  3334. }
  3335. setFromArray(array) {
  3336. let minX = +Infinity
  3337. let minY = +Infinity
  3338. let minZ = +Infinity
  3339. let maxX = -Infinity
  3340. let maxY = -Infinity
  3341. let maxZ = -Infinity
  3342. for (let i = 0, l = array.length; i < l; i += 3) {
  3343. const x = array[i]
  3344. const y = array[i + 1]
  3345. const z = array[i + 2]
  3346. if (x < minX) minX = x
  3347. if (y < minY) minY = y
  3348. if (z < minZ) minZ = z
  3349. if (x > maxX) maxX = x
  3350. if (y > maxY) maxY = y
  3351. if (z > maxZ) maxZ = z
  3352. }
  3353. this.min.set(minX, minY, minZ)
  3354. this.max.set(maxX, maxY, maxZ)
  3355. return this
  3356. }
  3357. setFromBufferAttribute(attribute) {
  3358. let minX = +Infinity
  3359. let minY = +Infinity
  3360. let minZ = +Infinity
  3361. let maxX = -Infinity
  3362. let maxY = -Infinity
  3363. let maxZ = -Infinity
  3364. for (let i = 0, l = attribute.count; i < l; i++) {
  3365. const x = attribute.getX(i)
  3366. const y = attribute.getY(i)
  3367. const z = attribute.getZ(i)
  3368. if (x < minX) minX = x
  3369. if (y < minY) minY = y
  3370. if (z < minZ) minZ = z
  3371. if (x > maxX) maxX = x
  3372. if (y > maxY) maxY = y
  3373. if (z > maxZ) maxZ = z
  3374. }
  3375. this.min.set(minX, minY, minZ)
  3376. this.max.set(maxX, maxY, maxZ)
  3377. return this
  3378. }
  3379. setFromPoints(points) {
  3380. this.makeEmpty()
  3381. for (let i = 0, il = points.length; i < il; i++) {
  3382. this.expandByPoint(points[i])
  3383. }
  3384. return this
  3385. }
  3386. setFromCenterAndSize(center, size) {
  3387. const halfSize = _vector$b.copy(size).multiplyScalar(0.5)
  3388. this.min.copy(center).sub(halfSize)
  3389. this.max.copy(center).add(halfSize)
  3390. return this
  3391. }
  3392. setFromObject(object, precise = false) {
  3393. this.makeEmpty()
  3394. return this.expandByObject(object, precise)
  3395. }
  3396. clone() {
  3397. return new this.constructor().copy(this)
  3398. }
  3399. copy(box) {
  3400. this.min.copy(box.min)
  3401. this.max.copy(box.max)
  3402. return this
  3403. }
  3404. makeEmpty() {
  3405. this.min.x = this.min.y = this.min.z = +Infinity
  3406. this.max.x = this.max.y = this.max.z = -Infinity
  3407. return this
  3408. }
  3409. isEmpty() {
  3410. // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  3411. return this.max.x < this.min.x || this.max.y < this.min.y || this.max.z < this.min.z
  3412. }
  3413. getCenter(target) {
  3414. return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5)
  3415. }
  3416. getSize(target) {
  3417. return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min)
  3418. }
  3419. expandByPoint(point) {
  3420. this.min.min(point)
  3421. this.max.max(point)
  3422. return this
  3423. }
  3424. expandByVector(vector) {
  3425. this.min.sub(vector)
  3426. this.max.add(vector)
  3427. return this
  3428. }
  3429. expandByScalar(scalar) {
  3430. this.min.addScalar(-scalar)
  3431. this.max.addScalar(scalar)
  3432. return this
  3433. }
  3434. expandByObject(object, precise = false) {
  3435. // Computes the world-axis-aligned bounding box of an object (including its children),
  3436. // accounting for both the object's, and children's, world transforms
  3437. object.updateWorldMatrix(false, false)
  3438. const geometry = object.geometry
  3439. if (geometry !== undefined) {
  3440. if (precise && geometry.attributes != undefined && geometry.attributes.position !== undefined) {
  3441. const position = geometry.attributes.position
  3442. for (let i = 0, l = position.count; i < l; i++) {
  3443. _vector$b.fromBufferAttribute(position, i).applyMatrix4(object.matrixWorld)
  3444. this.expandByPoint(_vector$b)
  3445. }
  3446. } else {
  3447. if (geometry.boundingBox === null) {
  3448. geometry.computeBoundingBox()
  3449. }
  3450. _box$3.copy(geometry.boundingBox)
  3451. _box$3.applyMatrix4(object.matrixWorld)
  3452. this.union(_box$3)
  3453. }
  3454. }
  3455. const children = object.children
  3456. for (let i = 0, l = children.length; i < l; i++) {
  3457. this.expandByObject(children[i], precise)
  3458. }
  3459. return this
  3460. }
  3461. containsPoint(point) {
  3462. return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z ? false : true
  3463. }
  3464. containsBox(box) {
  3465. return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y && this.min.z <= box.min.z && box.max.z <= this.max.z
  3466. }
  3467. getParameter(point, target) {
  3468. // This can potentially have a divide by zero if the box
  3469. // has a size dimension of 0.
  3470. return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z))
  3471. }
  3472. intersectsBox(box) {
  3473. // using 6 splitting planes to rule out intersections.
  3474. return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z ? false : true
  3475. }
  3476. intersectsSphere(sphere) {
  3477. // Find the point on the AABB closest to the sphere center.
  3478. this.clampPoint(sphere.center, _vector$b)
  3479. // If that point is inside the sphere, the AABB and sphere intersect.
  3480. return _vector$b.distanceToSquared(sphere.center) <= sphere.radius * sphere.radius
  3481. }
  3482. intersectsPlane(plane) {
  3483. // We compute the minimum and maximum dot product values. If those values
  3484. // are on the same side (back or front) of the plane, then there is no intersection.
  3485. let min, max
  3486. if (plane.normal.x > 0) {
  3487. min = plane.normal.x * this.min.x
  3488. max = plane.normal.x * this.max.x
  3489. } else {
  3490. min = plane.normal.x * this.max.x
  3491. max = plane.normal.x * this.min.x
  3492. }
  3493. if (plane.normal.y > 0) {
  3494. min += plane.normal.y * this.min.y
  3495. max += plane.normal.y * this.max.y
  3496. } else {
  3497. min += plane.normal.y * this.max.y
  3498. max += plane.normal.y * this.min.y
  3499. }
  3500. if (plane.normal.z > 0) {
  3501. min += plane.normal.z * this.min.z
  3502. max += plane.normal.z * this.max.z
  3503. } else {
  3504. min += plane.normal.z * this.max.z
  3505. max += plane.normal.z * this.min.z
  3506. }
  3507. return min <= -plane.constant && max >= -plane.constant
  3508. }
  3509. intersectsTriangle(triangle) {
  3510. if (this.isEmpty()) {
  3511. return false
  3512. }
  3513. // compute box center and extents
  3514. this.getCenter(_center)
  3515. _extents.subVectors(this.max, _center)
  3516. // translate triangle to aabb origin
  3517. _v0$2.subVectors(triangle.a, _center)
  3518. _v1$7.subVectors(triangle.b, _center)
  3519. _v2$3.subVectors(triangle.c, _center)
  3520. // compute edge vectors for triangle
  3521. _f0.subVectors(_v1$7, _v0$2)
  3522. _f1.subVectors(_v2$3, _v1$7)
  3523. _f2.subVectors(_v0$2, _v2$3)
  3524. // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
  3525. // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation
  3526. // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
  3527. let axes = [0, -_f0.z, _f0.y, 0, -_f1.z, _f1.y, 0, -_f2.z, _f2.y, _f0.z, 0, -_f0.x, _f1.z, 0, -_f1.x, _f2.z, 0, -_f2.x, -_f0.y, _f0.x, 0, -_f1.y, _f1.x, 0, -_f2.y, _f2.x, 0]
  3528. if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) {
  3529. return false
  3530. }
  3531. // test 3 face normals from the aabb
  3532. axes = [1, 0, 0, 0, 1, 0, 0, 0, 1]
  3533. if (!satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)) {
  3534. return false
  3535. }
  3536. // finally testing the face normal of the triangle
  3537. // use already existing triangle edge vectors here
  3538. _triangleNormal.crossVectors(_f0, _f1)
  3539. axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z]
  3540. return satForAxes(axes, _v0$2, _v1$7, _v2$3, _extents)
  3541. }
  3542. clampPoint(point, target) {
  3543. return target.copy(point).clamp(this.min, this.max)
  3544. }
  3545. distanceToPoint(point) {
  3546. const clampedPoint = _vector$b.copy(point).clamp(this.min, this.max)
  3547. return clampedPoint.sub(point).length()
  3548. }
  3549. getBoundingSphere(target) {
  3550. this.getCenter(target.center)
  3551. target.radius = this.getSize(_vector$b).length() * 0.5
  3552. return target
  3553. }
  3554. intersect(box) {
  3555. this.min.max(box.min)
  3556. this.max.min(box.max)
  3557. // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
  3558. if (this.isEmpty()) this.makeEmpty()
  3559. return this
  3560. }
  3561. union(box) {
  3562. this.min.min(box.min)
  3563. this.max.max(box.max)
  3564. return this
  3565. }
  3566. applyMatrix4(matrix) {
  3567. // transform of empty box is an empty box.
  3568. if (this.isEmpty()) return this
  3569. // NOTE: I am using a binary pattern to specify all 2^3 combinations below
  3570. _points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix) // 000
  3571. _points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix) // 001
  3572. _points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix) // 010
  3573. _points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix) // 011
  3574. _points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix) // 100
  3575. _points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix) // 101
  3576. _points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix) // 110
  3577. _points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix) // 111
  3578. this.setFromPoints(_points)
  3579. return this
  3580. }
  3581. translate(offset) {
  3582. this.min.add(offset)
  3583. this.max.add(offset)
  3584. return this
  3585. }
  3586. equals(box) {
  3587. return box.min.equals(this.min) && box.max.equals(this.max)
  3588. }
  3589. }
  3590. const _points = [
  3591. /*@__PURE__*/ new Vector3(),
  3592. /*@__PURE__*/ new Vector3(),
  3593. /*@__PURE__*/ new Vector3(),
  3594. /*@__PURE__*/ new Vector3(),
  3595. /*@__PURE__*/ new Vector3(),
  3596. /*@__PURE__*/ new Vector3(),
  3597. /*@__PURE__*/ new Vector3(),
  3598. /*@__PURE__*/ new Vector3()
  3599. ]
  3600. const _vector$b = /*@__PURE__*/ new Vector3()
  3601. const _box$3 = /*@__PURE__*/ new Box3()
  3602. // triangle centered vertices
  3603. const _v0$2 = /*@__PURE__*/ new Vector3()
  3604. const _v1$7 = /*@__PURE__*/ new Vector3()
  3605. const _v2$3 = /*@__PURE__*/ new Vector3()
  3606. // triangle edge vectors
  3607. const _f0 = /*@__PURE__*/ new Vector3()
  3608. const _f1 = /*@__PURE__*/ new Vector3()
  3609. const _f2 = /*@__PURE__*/ new Vector3()
  3610. const _center = /*@__PURE__*/ new Vector3()
  3611. const _extents = /*@__PURE__*/ new Vector3()
  3612. const _triangleNormal = /*@__PURE__*/ new Vector3()
  3613. const _testAxis = /*@__PURE__*/ new Vector3()
  3614. function satForAxes(axes, v0, v1, v2, extents) {
  3615. for (let i = 0, j = axes.length - 3; i <= j; i += 3) {
  3616. _testAxis.fromArray(axes, i)
  3617. // project the aabb onto the separating axis
  3618. const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z)
  3619. // project all 3 vertices of the triangle onto the separating axis
  3620. const p0 = v0.dot(_testAxis)
  3621. const p1 = v1.dot(_testAxis)
  3622. const p2 = v2.dot(_testAxis)
  3623. // actual test, basically see if either of the most extreme of the triangle points intersects r
  3624. if (Math.max(-Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {
  3625. // points of the projected triangle are outside the projected half-length of the aabb
  3626. // the axis is separating and we can exit
  3627. return false
  3628. }
  3629. }
  3630. return true
  3631. }
  3632. const _box$2 = /*@__PURE__*/ new Box3()
  3633. const _v1$6 = /*@__PURE__*/ new Vector3()
  3634. const _toFarthestPoint = /*@__PURE__*/ new Vector3()
  3635. const _toPoint = /*@__PURE__*/ new Vector3()
  3636. class Sphere {
  3637. constructor(center = new Vector3(), radius = -1) {
  3638. this.center = center
  3639. this.radius = radius
  3640. }
  3641. set(center, radius) {
  3642. this.center.copy(center)
  3643. this.radius = radius
  3644. return this
  3645. }
  3646. setFromPoints(points, optionalCenter) {
  3647. const center = this.center
  3648. if (optionalCenter !== undefined) {
  3649. center.copy(optionalCenter)
  3650. } else {
  3651. _box$2.setFromPoints(points).getCenter(center)
  3652. }
  3653. let maxRadiusSq = 0
  3654. for (let i = 0, il = points.length; i < il; i++) {
  3655. maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]))
  3656. }
  3657. this.radius = Math.sqrt(maxRadiusSq)
  3658. return this
  3659. }
  3660. copy(sphere) {
  3661. this.center.copy(sphere.center)
  3662. this.radius = sphere.radius
  3663. return this
  3664. }
  3665. isEmpty() {
  3666. return this.radius < 0
  3667. }
  3668. makeEmpty() {
  3669. this.center.set(0, 0, 0)
  3670. this.radius = -1
  3671. return this
  3672. }
  3673. containsPoint(point) {
  3674. return point.distanceToSquared(this.center) <= this.radius * this.radius
  3675. }
  3676. distanceToPoint(point) {
  3677. return point.distanceTo(this.center) - this.radius
  3678. }
  3679. intersectsSphere(sphere) {
  3680. const radiusSum = this.radius + sphere.radius
  3681. return sphere.center.distanceToSquared(this.center) <= radiusSum * radiusSum
  3682. }
  3683. intersectsBox(box) {
  3684. return box.intersectsSphere(this)
  3685. }
  3686. intersectsPlane(plane) {
  3687. return Math.abs(plane.distanceToPoint(this.center)) <= this.radius
  3688. }
  3689. clampPoint(point, target) {
  3690. const deltaLengthSq = this.center.distanceToSquared(point)
  3691. target.copy(point)
  3692. if (deltaLengthSq > this.radius * this.radius) {
  3693. target.sub(this.center).normalize()
  3694. target.multiplyScalar(this.radius).add(this.center)
  3695. }
  3696. return target
  3697. }
  3698. getBoundingBox(target) {
  3699. if (this.isEmpty()) {
  3700. // Empty sphere produces empty bounding box
  3701. target.makeEmpty()
  3702. return target
  3703. }
  3704. target.set(this.center, this.center)
  3705. target.expandByScalar(this.radius)
  3706. return target
  3707. }
  3708. applyMatrix4(matrix) {
  3709. this.center.applyMatrix4(matrix)
  3710. this.radius = this.radius * matrix.getMaxScaleOnAxis()
  3711. return this
  3712. }
  3713. translate(offset) {
  3714. this.center.add(offset)
  3715. return this
  3716. }
  3717. expandByPoint(point) {
  3718. // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L649-L671
  3719. _toPoint.subVectors(point, this.center)
  3720. const lengthSq = _toPoint.lengthSq()
  3721. if (lengthSq > this.radius * this.radius) {
  3722. const length = Math.sqrt(lengthSq)
  3723. const missingRadiusHalf = (length - this.radius) * 0.5
  3724. // Nudge this sphere towards the target point. Add half the missing distance to radius,
  3725. // and the other half to position. This gives a tighter enclosure, instead of if
  3726. // the whole missing distance were just added to radius.
  3727. this.center.add(_toPoint.multiplyScalar(missingRadiusHalf / length))
  3728. this.radius += missingRadiusHalf
  3729. }
  3730. return this
  3731. }
  3732. union(sphere) {
  3733. // from https://github.com/juj/MathGeoLib/blob/2940b99b99cfe575dd45103ef20f4019dee15b54/src/Geometry/Sphere.cpp#L759-L769
  3734. // To enclose another sphere into this sphere, we only need to enclose two points:
  3735. // 1) Enclose the farthest point on the other sphere into this sphere.
  3736. // 2) Enclose the opposite point of the farthest point into this sphere.
  3737. if (this.center.equals(sphere.center) === true) {
  3738. _toFarthestPoint.set(0, 0, 1).multiplyScalar(sphere.radius)
  3739. } else {
  3740. _toFarthestPoint
  3741. .subVectors(sphere.center, this.center)
  3742. .normalize()
  3743. .multiplyScalar(sphere.radius)
  3744. }
  3745. this.expandByPoint(_v1$6.copy(sphere.center).add(_toFarthestPoint))
  3746. this.expandByPoint(_v1$6.copy(sphere.center).sub(_toFarthestPoint))
  3747. return this
  3748. }
  3749. equals(sphere) {
  3750. return sphere.center.equals(this.center) && sphere.radius === this.radius
  3751. }
  3752. clone() {
  3753. return new this.constructor().copy(this)
  3754. }
  3755. }
  3756. const _vector$a = /*@__PURE__*/ new Vector3()
  3757. const _segCenter = /*@__PURE__*/ new Vector3()
  3758. const _segDir = /*@__PURE__*/ new Vector3()
  3759. const _diff = /*@__PURE__*/ new Vector3()
  3760. const _edge1 = /*@__PURE__*/ new Vector3()
  3761. const _edge2 = /*@__PURE__*/ new Vector3()
  3762. const _normal$1 = /*@__PURE__*/ new Vector3()
  3763. class Ray {
  3764. constructor(origin = new Vector3(), direction = new Vector3(0, 0, -1)) {
  3765. this.origin = origin
  3766. this.direction = direction
  3767. }
  3768. set(origin, direction) {
  3769. this.origin.copy(origin)
  3770. this.direction.copy(direction)
  3771. return this
  3772. }
  3773. copy(ray) {
  3774. this.origin.copy(ray.origin)
  3775. this.direction.copy(ray.direction)
  3776. return this
  3777. }
  3778. at(t, target) {
  3779. return target
  3780. .copy(this.direction)
  3781. .multiplyScalar(t)
  3782. .add(this.origin)
  3783. }
  3784. lookAt(v) {
  3785. this.direction
  3786. .copy(v)
  3787. .sub(this.origin)
  3788. .normalize()
  3789. return this
  3790. }
  3791. recast(t) {
  3792. this.origin.copy(this.at(t, _vector$a))
  3793. return this
  3794. }
  3795. closestPointToPoint(point, target) {
  3796. target.subVectors(point, this.origin)
  3797. const directionDistance = target.dot(this.direction)
  3798. if (directionDistance < 0) {
  3799. return target.copy(this.origin)
  3800. }
  3801. return target
  3802. .copy(this.direction)
  3803. .multiplyScalar(directionDistance)
  3804. .add(this.origin)
  3805. }
  3806. distanceToPoint(point) {
  3807. return Math.sqrt(this.distanceSqToPoint(point))
  3808. }
  3809. distanceSqToPoint(point) {
  3810. const directionDistance = _vector$a.subVectors(point, this.origin).dot(this.direction)
  3811. // point behind the ray
  3812. if (directionDistance < 0) {
  3813. return this.origin.distanceToSquared(point)
  3814. }
  3815. _vector$a
  3816. .copy(this.direction)
  3817. .multiplyScalar(directionDistance)
  3818. .add(this.origin)
  3819. return _vector$a.distanceToSquared(point)
  3820. }
  3821. distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) {
  3822. // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
  3823. // It returns the min distance between the ray and the segment
  3824. // defined by v0 and v1
  3825. // It can also set two optional targets :
  3826. // - The closest point on the ray
  3827. // - The closest point on the segment
  3828. _segCenter
  3829. .copy(v0)
  3830. .add(v1)
  3831. .multiplyScalar(0.5)
  3832. _segDir
  3833. .copy(v1)
  3834. .sub(v0)
  3835. .normalize()
  3836. _diff.copy(this.origin).sub(_segCenter)
  3837. const segExtent = v0.distanceTo(v1) * 0.5
  3838. const a01 = -this.direction.dot(_segDir)
  3839. const b0 = _diff.dot(this.direction)
  3840. const b1 = -_diff.dot(_segDir)
  3841. const c = _diff.lengthSq()
  3842. const det = Math.abs(1 - a01 * a01)
  3843. let s0, s1, sqrDist, extDet
  3844. if (det > 0) {
  3845. // The ray and segment are not parallel.
  3846. s0 = a01 * b1 - b0
  3847. s1 = a01 * b0 - b1
  3848. extDet = segExtent * det
  3849. if (s0 >= 0) {
  3850. if (s1 >= -extDet) {
  3851. if (s1 <= extDet) {
  3852. // region 0
  3853. // Minimum at interior points of ray and segment.
  3854. const invDet = 1 / det
  3855. s0 *= invDet
  3856. s1 *= invDet
  3857. sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c
  3858. } else {
  3859. // region 1
  3860. s1 = segExtent
  3861. s0 = Math.max(0, -(a01 * s1 + b0))
  3862. sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c
  3863. }
  3864. } else {
  3865. // region 5
  3866. s1 = -segExtent
  3867. s0 = Math.max(0, -(a01 * s1 + b0))
  3868. sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c
  3869. }
  3870. } else {
  3871. if (s1 <= -extDet) {
  3872. // region 4
  3873. s0 = Math.max(0, -(-a01 * segExtent + b0))
  3874. s1 = s0 > 0 ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent)
  3875. sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c
  3876. } else if (s1 <= extDet) {
  3877. // region 3
  3878. s0 = 0
  3879. s1 = Math.min(Math.max(-segExtent, -b1), segExtent)
  3880. sqrDist = s1 * (s1 + 2 * b1) + c
  3881. } else {
  3882. // region 2
  3883. s0 = Math.max(0, -(a01 * segExtent + b0))
  3884. s1 = s0 > 0 ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent)
  3885. sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c
  3886. }
  3887. }
  3888. } else {
  3889. // Ray and segment are parallel.
  3890. s1 = a01 > 0 ? -segExtent : segExtent
  3891. s0 = Math.max(0, -(a01 * s1 + b0))
  3892. sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c
  3893. }
  3894. if (optionalPointOnRay) {
  3895. optionalPointOnRay
  3896. .copy(this.direction)
  3897. .multiplyScalar(s0)
  3898. .add(this.origin)
  3899. }
  3900. if (optionalPointOnSegment) {
  3901. optionalPointOnSegment
  3902. .copy(_segDir)
  3903. .multiplyScalar(s1)
  3904. .add(_segCenter)
  3905. }
  3906. return sqrDist
  3907. }
  3908. intersectSphere(sphere, target) {
  3909. _vector$a.subVectors(sphere.center, this.origin)
  3910. const tca = _vector$a.dot(this.direction)
  3911. const d2 = _vector$a.dot(_vector$a) - tca * tca
  3912. const radius2 = sphere.radius * sphere.radius
  3913. if (d2 > radius2) return null
  3914. const thc = Math.sqrt(radius2 - d2)
  3915. // t0 = first intersect point - entrance on front of sphere
  3916. const t0 = tca - thc
  3917. // t1 = second intersect point - exit point on back of sphere
  3918. const t1 = tca + thc
  3919. // test to see if both t0 and t1 are behind the ray - if so, return null
  3920. if (t0 < 0 && t1 < 0) return null
  3921. // test to see if t0 is behind the ray:
  3922. // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
  3923. // in order to always return an intersect point that is in front of the ray.
  3924. if (t0 < 0) return this.at(t1, target)
  3925. // else t0 is in front of the ray, so return the first collision point scaled by t0
  3926. return this.at(t0, target)
  3927. }
  3928. intersectsSphere(sphere) {
  3929. return this.distanceSqToPoint(sphere.center) <= sphere.radius * sphere.radius
  3930. }
  3931. distanceToPlane(plane) {
  3932. const denominator = plane.normal.dot(this.direction)
  3933. if (denominator === 0) {
  3934. // line is coplanar, return origin
  3935. if (plane.distanceToPoint(this.origin) === 0) {
  3936. return 0
  3937. }
  3938. // Null is preferable to undefined since undefined means.... it is undefined
  3939. return null
  3940. }
  3941. const t = -(this.origin.dot(plane.normal) + plane.constant) / denominator
  3942. // Return if the ray never intersects the plane
  3943. return t >= 0 ? t : null
  3944. }
  3945. intersectPlane(plane, target) {
  3946. const t = this.distanceToPlane(plane)
  3947. if (t === null) {
  3948. return null
  3949. }
  3950. return this.at(t, target)
  3951. }
  3952. intersectsPlane(plane) {
  3953. // check if the ray lies on the plane first
  3954. const distToPoint = plane.distanceToPoint(this.origin)
  3955. if (distToPoint === 0) {
  3956. return true
  3957. }
  3958. const denominator = plane.normal.dot(this.direction)
  3959. if (denominator * distToPoint < 0) {
  3960. return true
  3961. }
  3962. // ray origin is behind the plane (and is pointing behind it)
  3963. return false
  3964. }
  3965. intersectBox(box, target) {
  3966. let tmin, tmax, tymin, tymax, tzmin, tzmax
  3967. const invdirx = 1 / this.direction.x,
  3968. invdiry = 1 / this.direction.y,
  3969. invdirz = 1 / this.direction.z
  3970. const origin = this.origin
  3971. if (invdirx >= 0) {
  3972. tmin = (box.min.x - origin.x) * invdirx
  3973. tmax = (box.max.x - origin.x) * invdirx
  3974. } else {
  3975. tmin = (box.max.x - origin.x) * invdirx
  3976. tmax = (box.min.x - origin.x) * invdirx
  3977. }
  3978. if (invdiry >= 0) {
  3979. tymin = (box.min.y - origin.y) * invdiry
  3980. tymax = (box.max.y - origin.y) * invdiry
  3981. } else {
  3982. tymin = (box.max.y - origin.y) * invdiry
  3983. tymax = (box.min.y - origin.y) * invdiry
  3984. }
  3985. if (tmin > tymax || tymin > tmax) return null
  3986. // These lines also handle the case where tmin or tmax is NaN
  3987. // (result of 0 * Infinity). x !== x returns true if x is NaN
  3988. if (tymin > tmin || tmin !== tmin) tmin = tymin
  3989. if (tymax < tmax || tmax !== tmax) tmax = tymax
  3990. if (invdirz >= 0) {
  3991. tzmin = (box.min.z - origin.z) * invdirz
  3992. tzmax = (box.max.z - origin.z) * invdirz
  3993. } else {
  3994. tzmin = (box.max.z - origin.z) * invdirz
  3995. tzmax = (box.min.z - origin.z) * invdirz
  3996. }
  3997. if (tmin > tzmax || tzmin > tmax) return null
  3998. if (tzmin > tmin || tmin !== tmin) tmin = tzmin
  3999. if (tzmax < tmax || tmax !== tmax) tmax = tzmax
  4000. //return point closest to the ray (positive side)
  4001. if (tmax < 0) return null
  4002. return this.at(tmin >= 0 ? tmin : tmax, target)
  4003. }
  4004. intersectsBox(box) {
  4005. return this.intersectBox(box, _vector$a) !== null
  4006. }
  4007. intersectTriangle(a, b, c, backfaceCulling, target) {
  4008. // Compute the offset origin, edges, and normal.
  4009. // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
  4010. _edge1.subVectors(b, a)
  4011. _edge2.subVectors(c, a)
  4012. _normal$1.crossVectors(_edge1, _edge2)
  4013. // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
  4014. // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
  4015. // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
  4016. // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
  4017. // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
  4018. let DdN = this.direction.dot(_normal$1)
  4019. let sign
  4020. if (DdN > 0) {
  4021. if (backfaceCulling) return null
  4022. sign = 1
  4023. } else if (DdN < 0) {
  4024. sign = -1
  4025. DdN = -DdN
  4026. } else {
  4027. return null
  4028. }
  4029. _diff.subVectors(this.origin, a)
  4030. const DdQxE2 = sign * this.direction.dot(_edge2.crossVectors(_diff, _edge2))
  4031. // b1 < 0, no intersection
  4032. if (DdQxE2 < 0) {
  4033. return null
  4034. }
  4035. const DdE1xQ = sign * this.direction.dot(_edge1.cross(_diff))
  4036. // b2 < 0, no intersection
  4037. if (DdE1xQ < 0) {
  4038. return null
  4039. }
  4040. // b1+b2 > 1, no intersection
  4041. if (DdQxE2 + DdE1xQ > DdN) {
  4042. return null
  4043. }
  4044. // Line intersects triangle, check if ray does.
  4045. const QdN = -sign * _diff.dot(_normal$1)
  4046. // t < 0, no intersection
  4047. if (QdN < 0) {
  4048. return null
  4049. }
  4050. // Ray intersects triangle.
  4051. return this.at(QdN / DdN, target)
  4052. }
  4053. applyMatrix4(matrix4) {
  4054. this.origin.applyMatrix4(matrix4)
  4055. this.direction.transformDirection(matrix4)
  4056. return this
  4057. }
  4058. equals(ray) {
  4059. return ray.origin.equals(this.origin) && ray.direction.equals(this.direction)
  4060. }
  4061. clone() {
  4062. return new this.constructor().copy(this)
  4063. }
  4064. }
  4065. class Matrix4 {
  4066. constructor() {
  4067. this.isMatrix4 = true
  4068. this.elements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
  4069. if (arguments.length > 0) {
  4070. console.error('THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.')
  4071. }
  4072. }
  4073. set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
  4074. const te = this.elements
  4075. te[0] = n11
  4076. te[4] = n12
  4077. te[8] = n13
  4078. te[12] = n14
  4079. te[1] = n21
  4080. te[5] = n22
  4081. te[9] = n23
  4082. te[13] = n24
  4083. te[2] = n31
  4084. te[6] = n32
  4085. te[10] = n33
  4086. te[14] = n34
  4087. te[3] = n41
  4088. te[7] = n42
  4089. te[11] = n43
  4090. te[15] = n44
  4091. return this
  4092. }
  4093. identity() {
  4094. this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  4095. return this
  4096. }
  4097. clone() {
  4098. return new Matrix4().fromArray(this.elements)
  4099. }
  4100. copy(m) {
  4101. const te = this.elements
  4102. const me = m.elements
  4103. te[0] = me[0]
  4104. te[1] = me[1]
  4105. te[2] = me[2]
  4106. te[3] = me[3]
  4107. te[4] = me[4]
  4108. te[5] = me[5]
  4109. te[6] = me[6]
  4110. te[7] = me[7]
  4111. te[8] = me[8]
  4112. te[9] = me[9]
  4113. te[10] = me[10]
  4114. te[11] = me[11]
  4115. te[12] = me[12]
  4116. te[13] = me[13]
  4117. te[14] = me[14]
  4118. te[15] = me[15]
  4119. return this
  4120. }
  4121. copyPosition(m) {
  4122. const te = this.elements,
  4123. me = m.elements
  4124. te[12] = me[12]
  4125. te[13] = me[13]
  4126. te[14] = me[14]
  4127. return this
  4128. }
  4129. setFromMatrix3(m) {
  4130. const me = m.elements
  4131. this.set(me[0], me[3], me[6], 0, me[1], me[4], me[7], 0, me[2], me[5], me[8], 0, 0, 0, 0, 1)
  4132. return this
  4133. }
  4134. extractBasis(xAxis, yAxis, zAxis) {
  4135. xAxis.setFromMatrixColumn(this, 0)
  4136. yAxis.setFromMatrixColumn(this, 1)
  4137. zAxis.setFromMatrixColumn(this, 2)
  4138. return this
  4139. }
  4140. makeBasis(xAxis, yAxis, zAxis) {
  4141. this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1)
  4142. return this
  4143. }
  4144. extractRotation(m) {
  4145. // this method does not support reflection matrices
  4146. const te = this.elements
  4147. const me = m.elements
  4148. const scaleX = 1 / _v1$5.setFromMatrixColumn(m, 0).length()
  4149. const scaleY = 1 / _v1$5.setFromMatrixColumn(m, 1).length()
  4150. const scaleZ = 1 / _v1$5.setFromMatrixColumn(m, 2).length()
  4151. te[0] = me[0] * scaleX
  4152. te[1] = me[1] * scaleX
  4153. te[2] = me[2] * scaleX
  4154. te[3] = 0
  4155. te[4] = me[4] * scaleY
  4156. te[5] = me[5] * scaleY
  4157. te[6] = me[6] * scaleY
  4158. te[7] = 0
  4159. te[8] = me[8] * scaleZ
  4160. te[9] = me[9] * scaleZ
  4161. te[10] = me[10] * scaleZ
  4162. te[11] = 0
  4163. te[12] = 0
  4164. te[13] = 0
  4165. te[14] = 0
  4166. te[15] = 1
  4167. return this
  4168. }
  4169. makeRotationFromEuler(euler) {
  4170. if (!(euler && euler.isEuler)) {
  4171. console.error('THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.')
  4172. }
  4173. const te = this.elements
  4174. const x = euler.x,
  4175. y = euler.y,
  4176. z = euler.z
  4177. const a = Math.cos(x),
  4178. b = Math.sin(x)
  4179. const c = Math.cos(y),
  4180. d = Math.sin(y)
  4181. const e = Math.cos(z),
  4182. f = Math.sin(z)
  4183. if (euler.order === 'XYZ') {
  4184. const ae = a * e,
  4185. af = a * f,
  4186. be = b * e,
  4187. bf = b * f
  4188. te[0] = c * e
  4189. te[4] = -c * f
  4190. te[8] = d
  4191. te[1] = af + be * d
  4192. te[5] = ae - bf * d
  4193. te[9] = -b * c
  4194. te[2] = bf - ae * d
  4195. te[6] = be + af * d
  4196. te[10] = a * c
  4197. } else if (euler.order === 'YXZ') {
  4198. const ce = c * e,
  4199. cf = c * f,
  4200. de = d * e,
  4201. df = d * f
  4202. te[0] = ce + df * b
  4203. te[4] = de * b - cf
  4204. te[8] = a * d
  4205. te[1] = a * f
  4206. te[5] = a * e
  4207. te[9] = -b
  4208. te[2] = cf * b - de
  4209. te[6] = df + ce * b
  4210. te[10] = a * c
  4211. } else if (euler.order === 'ZXY') {
  4212. const ce = c * e,
  4213. cf = c * f,
  4214. de = d * e,
  4215. df = d * f
  4216. te[0] = ce - df * b
  4217. te[4] = -a * f
  4218. te[8] = de + cf * b
  4219. te[1] = cf + de * b
  4220. te[5] = a * e
  4221. te[9] = df - ce * b
  4222. te[2] = -a * d
  4223. te[6] = b
  4224. te[10] = a * c
  4225. } else if (euler.order === 'ZYX') {
  4226. const ae = a * e,
  4227. af = a * f,
  4228. be = b * e,
  4229. bf = b * f
  4230. te[0] = c * e
  4231. te[4] = be * d - af
  4232. te[8] = ae * d + bf
  4233. te[1] = c * f
  4234. te[5] = bf * d + ae
  4235. te[9] = af * d - be
  4236. te[2] = -d
  4237. te[6] = b * c
  4238. te[10] = a * c
  4239. } else if (euler.order === 'YZX') {
  4240. const ac = a * c,
  4241. ad = a * d,
  4242. bc = b * c,
  4243. bd = b * d
  4244. te[0] = c * e
  4245. te[4] = bd - ac * f
  4246. te[8] = bc * f + ad
  4247. te[1] = f
  4248. te[5] = a * e
  4249. te[9] = -b * e
  4250. te[2] = -d * e
  4251. te[6] = ad * f + bc
  4252. te[10] = ac - bd * f
  4253. } else if (euler.order === 'XZY') {
  4254. const ac = a * c,
  4255. ad = a * d,
  4256. bc = b * c,
  4257. bd = b * d
  4258. te[0] = c * e
  4259. te[4] = -f
  4260. te[8] = d * e
  4261. te[1] = ac * f + bd
  4262. te[5] = a * e
  4263. te[9] = ad * f - bc
  4264. te[2] = bc * f - ad
  4265. te[6] = b * e
  4266. te[10] = bd * f + ac
  4267. }
  4268. // bottom row
  4269. te[3] = 0
  4270. te[7] = 0
  4271. te[11] = 0
  4272. // last column
  4273. te[12] = 0
  4274. te[13] = 0
  4275. te[14] = 0
  4276. te[15] = 1
  4277. return this
  4278. }
  4279. makeRotationFromQuaternion(q) {
  4280. return this.compose(_zero, q, _one)
  4281. }
  4282. lookAt(eye, target, up) {
  4283. const te = this.elements
  4284. _z.subVectors(eye, target)
  4285. if (_z.lengthSq() === 0) {
  4286. // eye and target are in the same position
  4287. _z.z = 1
  4288. }
  4289. _z.normalize()
  4290. _x.crossVectors(up, _z)
  4291. if (_x.lengthSq() === 0) {
  4292. // up and z are parallel
  4293. if (Math.abs(up.z) === 1) {
  4294. _z.x += 0.0001
  4295. } else {
  4296. _z.z += 0.0001
  4297. }
  4298. _z.normalize()
  4299. _x.crossVectors(up, _z)
  4300. }
  4301. _x.normalize()
  4302. _y.crossVectors(_z, _x)
  4303. te[0] = _x.x
  4304. te[4] = _y.x
  4305. te[8] = _z.x
  4306. te[1] = _x.y
  4307. te[5] = _y.y
  4308. te[9] = _z.y
  4309. te[2] = _x.z
  4310. te[6] = _y.z
  4311. te[10] = _z.z
  4312. return this
  4313. }
  4314. multiply(m, n) {
  4315. if (n !== undefined) {
  4316. console.warn('THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.')
  4317. return this.multiplyMatrices(m, n)
  4318. }
  4319. return this.multiplyMatrices(this, m)
  4320. }
  4321. premultiply(m) {
  4322. return this.multiplyMatrices(m, this)
  4323. }
  4324. multiplyMatrices(a, b) {
  4325. const ae = a.elements
  4326. const be = b.elements
  4327. const te = this.elements
  4328. const a11 = ae[0],
  4329. a12 = ae[4],
  4330. a13 = ae[8],
  4331. a14 = ae[12]
  4332. const a21 = ae[1],
  4333. a22 = ae[5],
  4334. a23 = ae[9],
  4335. a24 = ae[13]
  4336. const a31 = ae[2],
  4337. a32 = ae[6],
  4338. a33 = ae[10],
  4339. a34 = ae[14]
  4340. const a41 = ae[3],
  4341. a42 = ae[7],
  4342. a43 = ae[11],
  4343. a44 = ae[15]
  4344. const b11 = be[0],
  4345. b12 = be[4],
  4346. b13 = be[8],
  4347. b14 = be[12]
  4348. const b21 = be[1],
  4349. b22 = be[5],
  4350. b23 = be[9],
  4351. b24 = be[13]
  4352. const b31 = be[2],
  4353. b32 = be[6],
  4354. b33 = be[10],
  4355. b34 = be[14]
  4356. const b41 = be[3],
  4357. b42 = be[7],
  4358. b43 = be[11],
  4359. b44 = be[15]
  4360. te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41
  4361. te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42
  4362. te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43
  4363. te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44
  4364. te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41
  4365. te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42
  4366. te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43
  4367. te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44
  4368. te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41
  4369. te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42
  4370. te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43
  4371. te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44
  4372. te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41
  4373. te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42
  4374. te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43
  4375. te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44
  4376. return this
  4377. }
  4378. multiplyScalar(s) {
  4379. const te = this.elements
  4380. te[0] *= s
  4381. te[4] *= s
  4382. te[8] *= s
  4383. te[12] *= s
  4384. te[1] *= s
  4385. te[5] *= s
  4386. te[9] *= s
  4387. te[13] *= s
  4388. te[2] *= s
  4389. te[6] *= s
  4390. te[10] *= s
  4391. te[14] *= s
  4392. te[3] *= s
  4393. te[7] *= s
  4394. te[11] *= s
  4395. te[15] *= s
  4396. return this
  4397. }
  4398. determinant() {
  4399. const te = this.elements
  4400. const n11 = te[0],
  4401. n12 = te[4],
  4402. n13 = te[8],
  4403. n14 = te[12]
  4404. const n21 = te[1],
  4405. n22 = te[5],
  4406. n23 = te[9],
  4407. n24 = te[13]
  4408. const n31 = te[2],
  4409. n32 = te[6],
  4410. n33 = te[10],
  4411. n34 = te[14]
  4412. const n41 = te[3],
  4413. n42 = te[7],
  4414. n43 = te[11],
  4415. n44 = te[15]
  4416. //TODO: make this more efficient
  4417. //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  4418. return (
  4419. n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) +
  4420. n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) +
  4421. n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) +
  4422. n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31)
  4423. )
  4424. }
  4425. transpose() {
  4426. const te = this.elements
  4427. let tmp
  4428. tmp = te[1]
  4429. te[1] = te[4]
  4430. te[4] = tmp
  4431. tmp = te[2]
  4432. te[2] = te[8]
  4433. te[8] = tmp
  4434. tmp = te[6]
  4435. te[6] = te[9]
  4436. te[9] = tmp
  4437. tmp = te[3]
  4438. te[3] = te[12]
  4439. te[12] = tmp
  4440. tmp = te[7]
  4441. te[7] = te[13]
  4442. te[13] = tmp
  4443. tmp = te[11]
  4444. te[11] = te[14]
  4445. te[14] = tmp
  4446. return this
  4447. }
  4448. setPosition(x, y, z) {
  4449. const te = this.elements
  4450. if (x.isVector3) {
  4451. te[12] = x.x
  4452. te[13] = x.y
  4453. te[14] = x.z
  4454. } else {
  4455. te[12] = x
  4456. te[13] = y
  4457. te[14] = z
  4458. }
  4459. return this
  4460. }
  4461. invert() {
  4462. // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
  4463. const te = this.elements,
  4464. n11 = te[0],
  4465. n21 = te[1],
  4466. n31 = te[2],
  4467. n41 = te[3],
  4468. n12 = te[4],
  4469. n22 = te[5],
  4470. n32 = te[6],
  4471. n42 = te[7],
  4472. n13 = te[8],
  4473. n23 = te[9],
  4474. n33 = te[10],
  4475. n43 = te[11],
  4476. n14 = te[12],
  4477. n24 = te[13],
  4478. n34 = te[14],
  4479. n44 = te[15],
  4480. t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
  4481. t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
  4482. t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
  4483. t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34
  4484. const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14
  4485. if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  4486. const detInv = 1 / det
  4487. te[0] = t11 * detInv
  4488. te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv
  4489. te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv
  4490. te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv
  4491. te[4] = t12 * detInv
  4492. te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv
  4493. te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv
  4494. te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv
  4495. te[8] = t13 * detInv
  4496. te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv
  4497. te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv
  4498. te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv
  4499. te[12] = t14 * detInv
  4500. te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv
  4501. te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv
  4502. te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv
  4503. return this
  4504. }
  4505. scale(v) {
  4506. const te = this.elements
  4507. const x = v.x,
  4508. y = v.y,
  4509. z = v.z
  4510. te[0] *= x
  4511. te[4] *= y
  4512. te[8] *= z
  4513. te[1] *= x
  4514. te[5] *= y
  4515. te[9] *= z
  4516. te[2] *= x
  4517. te[6] *= y
  4518. te[10] *= z
  4519. te[3] *= x
  4520. te[7] *= y
  4521. te[11] *= z
  4522. return this
  4523. }
  4524. getMaxScaleOnAxis() {
  4525. const te = this.elements
  4526. const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2]
  4527. const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6]
  4528. const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10]
  4529. return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq))
  4530. }
  4531. makeTranslation(x, y, z) {
  4532. this.set(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1)
  4533. return this
  4534. }
  4535. makeRotationX(theta) {
  4536. const c = Math.cos(theta),
  4537. s = Math.sin(theta)
  4538. this.set(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1)
  4539. return this
  4540. }
  4541. makeRotationY(theta) {
  4542. const c = Math.cos(theta),
  4543. s = Math.sin(theta)
  4544. this.set(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1)
  4545. return this
  4546. }
  4547. makeRotationZ(theta) {
  4548. const c = Math.cos(theta),
  4549. s = Math.sin(theta)
  4550. this.set(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
  4551. return this
  4552. }
  4553. makeRotationAxis(axis, angle) {
  4554. // Based on http://www.gamedev.net/reference/articles/article1199.asp
  4555. const c = Math.cos(angle)
  4556. const s = Math.sin(angle)
  4557. const t = 1 - c
  4558. const x = axis.x,
  4559. y = axis.y,
  4560. z = axis.z
  4561. const tx = t * x,
  4562. ty = t * y
  4563. this.set(tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1)
  4564. return this
  4565. }
  4566. makeScale(x, y, z) {
  4567. this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1)
  4568. return this
  4569. }
  4570. makeShear(xy, xz, yx, yz, zx, zy) {
  4571. this.set(1, yx, zx, 0, xy, 1, zy, 0, xz, yz, 1, 0, 0, 0, 0, 1)
  4572. return this
  4573. }
  4574. compose(position, quaternion, scale) {
  4575. const te = this.elements
  4576. const x = quaternion._x,
  4577. y = quaternion._y,
  4578. z = quaternion._z,
  4579. w = quaternion._w
  4580. const x2 = x + x,
  4581. y2 = y + y,
  4582. z2 = z + z
  4583. const xx = x * x2,
  4584. xy = x * y2,
  4585. xz = x * z2
  4586. const yy = y * y2,
  4587. yz = y * z2,
  4588. zz = z * z2
  4589. const wx = w * x2,
  4590. wy = w * y2,
  4591. wz = w * z2
  4592. const sx = scale.x,
  4593. sy = scale.y,
  4594. sz = scale.z
  4595. te[0] = (1 - (yy + zz)) * sx
  4596. te[1] = (xy + wz) * sx
  4597. te[2] = (xz - wy) * sx
  4598. te[3] = 0
  4599. te[4] = (xy - wz) * sy
  4600. te[5] = (1 - (xx + zz)) * sy
  4601. te[6] = (yz + wx) * sy
  4602. te[7] = 0
  4603. te[8] = (xz + wy) * sz
  4604. te[9] = (yz - wx) * sz
  4605. te[10] = (1 - (xx + yy)) * sz
  4606. te[11] = 0
  4607. te[12] = position.x
  4608. te[13] = position.y
  4609. te[14] = position.z
  4610. te[15] = 1
  4611. return this
  4612. }
  4613. decompose(position, quaternion, scale) {
  4614. const te = this.elements
  4615. let sx = _v1$5.set(te[0], te[1], te[2]).length()
  4616. const sy = _v1$5.set(te[4], te[5], te[6]).length()
  4617. const sz = _v1$5.set(te[8], te[9], te[10]).length()
  4618. // if determine is negative, we need to invert one scale
  4619. const det = this.determinant()
  4620. if (det < 0) sx = -sx
  4621. position.x = te[12]
  4622. position.y = te[13]
  4623. position.z = te[14]
  4624. // scale the rotation part
  4625. _m1$2.copy(this)
  4626. const invSX = 1 / sx
  4627. const invSY = 1 / sy
  4628. const invSZ = 1 / sz
  4629. _m1$2.elements[0] *= invSX
  4630. _m1$2.elements[1] *= invSX
  4631. _m1$2.elements[2] *= invSX
  4632. _m1$2.elements[4] *= invSY
  4633. _m1$2.elements[5] *= invSY
  4634. _m1$2.elements[6] *= invSY
  4635. _m1$2.elements[8] *= invSZ
  4636. _m1$2.elements[9] *= invSZ
  4637. _m1$2.elements[10] *= invSZ
  4638. quaternion.setFromRotationMatrix(_m1$2)
  4639. scale.x = sx
  4640. scale.y = sy
  4641. scale.z = sz
  4642. return this
  4643. }
  4644. makePerspective(left, right, top, bottom, near, far) {
  4645. if (far === undefined) {
  4646. console.warn('THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.')
  4647. }
  4648. const te = this.elements
  4649. const x = (2 * near) / (right - left)
  4650. const y = (2 * near) / (top - bottom)
  4651. const a = (right + left) / (right - left)
  4652. const b = (top + bottom) / (top - bottom)
  4653. const c = -(far + near) / (far - near)
  4654. const d = (-2 * far * near) / (far - near)
  4655. te[0] = x
  4656. te[4] = 0
  4657. te[8] = a
  4658. te[12] = 0
  4659. te[1] = 0
  4660. te[5] = y
  4661. te[9] = b
  4662. te[13] = 0
  4663. te[2] = 0
  4664. te[6] = 0
  4665. te[10] = c
  4666. te[14] = d
  4667. te[3] = 0
  4668. te[7] = 0
  4669. te[11] = -1
  4670. te[15] = 0
  4671. return this
  4672. }
  4673. makeOrthographic(left, right, top, bottom, near, far) {
  4674. const te = this.elements
  4675. const w = 1.0 / (right - left)
  4676. const h = 1.0 / (top - bottom)
  4677. const p = 1.0 / (far - near)
  4678. const x = (right + left) * w
  4679. const y = (top + bottom) * h
  4680. const z = (far + near) * p
  4681. te[0] = 2 * w
  4682. te[4] = 0
  4683. te[8] = 0
  4684. te[12] = -x
  4685. te[1] = 0
  4686. te[5] = 2 * h
  4687. te[9] = 0
  4688. te[13] = -y
  4689. te[2] = 0
  4690. te[6] = 0
  4691. te[10] = -2 * p
  4692. te[14] = -z
  4693. te[3] = 0
  4694. te[7] = 0
  4695. te[11] = 0
  4696. te[15] = 1
  4697. return this
  4698. }
  4699. equals(matrix) {
  4700. const te = this.elements
  4701. const me = matrix.elements
  4702. for (let i = 0; i < 16; i++) {
  4703. if (te[i] !== me[i]) return false
  4704. }
  4705. return true
  4706. }
  4707. fromArray(array, offset = 0) {
  4708. for (let i = 0; i < 16; i++) {
  4709. this.elements[i] = array[i + offset]
  4710. }
  4711. return this
  4712. }
  4713. toArray(array = [], offset = 0) {
  4714. const te = this.elements
  4715. array[offset] = te[0]
  4716. array[offset + 1] = te[1]
  4717. array[offset + 2] = te[2]
  4718. array[offset + 3] = te[3]
  4719. array[offset + 4] = te[4]
  4720. array[offset + 5] = te[5]
  4721. array[offset + 6] = te[6]
  4722. array[offset + 7] = te[7]
  4723. array[offset + 8] = te[8]
  4724. array[offset + 9] = te[9]
  4725. array[offset + 10] = te[10]
  4726. array[offset + 11] = te[11]
  4727. array[offset + 12] = te[12]
  4728. array[offset + 13] = te[13]
  4729. array[offset + 14] = te[14]
  4730. array[offset + 15] = te[15]
  4731. return array
  4732. }
  4733. }
  4734. const _v1$5 = /*@__PURE__*/ new Vector3()
  4735. const _m1$2 = /*@__PURE__*/ new Matrix4()
  4736. const _zero = /*@__PURE__*/ new Vector3(0, 0, 0)
  4737. const _one = /*@__PURE__*/ new Vector3(1, 1, 1)
  4738. const _x = /*@__PURE__*/ new Vector3()
  4739. const _y = /*@__PURE__*/ new Vector3()
  4740. const _z = /*@__PURE__*/ new Vector3()
  4741. const _matrix$1 = /*@__PURE__*/ new Matrix4()
  4742. const _quaternion$3 = /*@__PURE__*/ new Quaternion()
  4743. class Euler {
  4744. constructor(x = 0, y = 0, z = 0, order = Euler.DefaultOrder) {
  4745. this.isEuler = true
  4746. this._x = x
  4747. this._y = y
  4748. this._z = z
  4749. this._order = order
  4750. }
  4751. get x() {
  4752. return this._x
  4753. }
  4754. set x(value) {
  4755. this._x = value
  4756. this._onChangeCallback()
  4757. }
  4758. get y() {
  4759. return this._y
  4760. }
  4761. set y(value) {
  4762. this._y = value
  4763. this._onChangeCallback()
  4764. }
  4765. get z() {
  4766. return this._z
  4767. }
  4768. set z(value) {
  4769. this._z = value
  4770. this._onChangeCallback()
  4771. }
  4772. get order() {
  4773. return this._order
  4774. }
  4775. set order(value) {
  4776. this._order = value
  4777. this._onChangeCallback()
  4778. }
  4779. set(x, y, z, order = this._order) {
  4780. this._x = x
  4781. this._y = y
  4782. this._z = z
  4783. this._order = order
  4784. this._onChangeCallback()
  4785. return this
  4786. }
  4787. clone() {
  4788. return new this.constructor(this._x, this._y, this._z, this._order)
  4789. }
  4790. copy(euler) {
  4791. this._x = euler._x
  4792. this._y = euler._y
  4793. this._z = euler._z
  4794. this._order = euler._order
  4795. this._onChangeCallback()
  4796. return this
  4797. }
  4798. setFromRotationMatrix(m, order = this._order, update = true) {
  4799. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  4800. const te = m.elements
  4801. const m11 = te[0],
  4802. m12 = te[4],
  4803. m13 = te[8]
  4804. const m21 = te[1],
  4805. m22 = te[5],
  4806. m23 = te[9]
  4807. const m31 = te[2],
  4808. m32 = te[6],
  4809. m33 = te[10]
  4810. switch (order) {
  4811. case 'XYZ':
  4812. this._y = Math.asin(clamp(m13, -1, 1))
  4813. if (Math.abs(m13) < 0.9999999) {
  4814. this._x = Math.atan2(-m23, m33)
  4815. this._z = Math.atan2(-m12, m11)
  4816. } else {
  4817. this._x = Math.atan2(m32, m22)
  4818. this._z = 0
  4819. }
  4820. break
  4821. case 'YXZ':
  4822. this._x = Math.asin(-clamp(m23, -1, 1))
  4823. if (Math.abs(m23) < 0.9999999) {
  4824. this._y = Math.atan2(m13, m33)
  4825. this._z = Math.atan2(m21, m22)
  4826. } else {
  4827. this._y = Math.atan2(-m31, m11)
  4828. this._z = 0
  4829. }
  4830. break
  4831. case 'ZXY':
  4832. this._x = Math.asin(clamp(m32, -1, 1))
  4833. if (Math.abs(m32) < 0.9999999) {
  4834. this._y = Math.atan2(-m31, m33)
  4835. this._z = Math.atan2(-m12, m22)
  4836. } else {
  4837. this._y = 0
  4838. this._z = Math.atan2(m21, m11)
  4839. }
  4840. break
  4841. case 'ZYX':
  4842. this._y = Math.asin(-clamp(m31, -1, 1))
  4843. if (Math.abs(m31) < 0.9999999) {
  4844. this._x = Math.atan2(m32, m33)
  4845. this._z = Math.atan2(m21, m11)
  4846. } else {
  4847. this._x = 0
  4848. this._z = Math.atan2(-m12, m22)
  4849. }
  4850. break
  4851. case 'YZX':
  4852. this._z = Math.asin(clamp(m21, -1, 1))
  4853. if (Math.abs(m21) < 0.9999999) {
  4854. this._x = Math.atan2(-m23, m22)
  4855. this._y = Math.atan2(-m31, m11)
  4856. } else {
  4857. this._x = 0
  4858. this._y = Math.atan2(m13, m33)
  4859. }
  4860. break
  4861. case 'XZY':
  4862. this._z = Math.asin(-clamp(m12, -1, 1))
  4863. if (Math.abs(m12) < 0.9999999) {
  4864. this._x = Math.atan2(m32, m22)
  4865. this._y = Math.atan2(m13, m11)
  4866. } else {
  4867. this._x = Math.atan2(-m23, m33)
  4868. this._y = 0
  4869. }
  4870. break
  4871. default:
  4872. console.warn('THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order)
  4873. }
  4874. this._order = order
  4875. if (update === true) this._onChangeCallback()
  4876. return this
  4877. }
  4878. setFromQuaternion(q, order, update) {
  4879. _matrix$1.makeRotationFromQuaternion(q)
  4880. return this.setFromRotationMatrix(_matrix$1, order, update)
  4881. }
  4882. setFromVector3(v, order = this._order) {
  4883. return this.set(v.x, v.y, v.z, order)
  4884. }
  4885. reorder(newOrder) {
  4886. // WARNING: this discards revolution information -bhouston
  4887. _quaternion$3.setFromEuler(this)
  4888. return this.setFromQuaternion(_quaternion$3, newOrder)
  4889. }
  4890. equals(euler) {
  4891. return euler._x === this._x && euler._y === this._y && euler._z === this._z && euler._order === this._order
  4892. }
  4893. fromArray(array) {
  4894. this._x = array[0]
  4895. this._y = array[1]
  4896. this._z = array[2]
  4897. if (array[3] !== undefined) this._order = array[3]
  4898. this._onChangeCallback()
  4899. return this
  4900. }
  4901. toArray(array = [], offset = 0) {
  4902. array[offset] = this._x
  4903. array[offset + 1] = this._y
  4904. array[offset + 2] = this._z
  4905. array[offset + 3] = this._order
  4906. return array
  4907. }
  4908. _onChange(callback) {
  4909. this._onChangeCallback = callback
  4910. return this
  4911. }
  4912. _onChangeCallback() {}
  4913. *[Symbol.iterator]() {
  4914. yield this._x
  4915. yield this._y
  4916. yield this._z
  4917. yield this._order
  4918. }
  4919. // @deprecated since r138, 02cf0df1cb4575d5842fef9c85bb5a89fe020d53
  4920. toVector3() {
  4921. console.error('THREE.Euler: .toVector3() has been removed. Use Vector3.setFromEuler() instead')
  4922. }
  4923. }
  4924. Euler.DefaultOrder = 'XYZ'
  4925. Euler.RotationOrders = ['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX']
  4926. class Layers {
  4927. constructor() {
  4928. this.mask = 1 | 0
  4929. }
  4930. set(channel) {
  4931. this.mask = ((1 << channel) | 0) >>> 0
  4932. }
  4933. enable(channel) {
  4934. this.mask |= (1 << channel) | 0
  4935. }
  4936. enableAll() {
  4937. this.mask = 0xffffffff | 0
  4938. }
  4939. toggle(channel) {
  4940. this.mask ^= (1 << channel) | 0
  4941. }
  4942. disable(channel) {
  4943. this.mask &= ~((1 << channel) | 0)
  4944. }
  4945. disableAll() {
  4946. this.mask = 0
  4947. }
  4948. test(layers) {
  4949. return (this.mask & layers.mask) !== 0
  4950. }
  4951. isEnabled(channel) {
  4952. return (this.mask & ((1 << channel) | 0)) !== 0
  4953. }
  4954. }
  4955. let _object3DId = 0
  4956. const _v1$4 = /*@__PURE__*/ new Vector3()
  4957. const _q1 = /*@__PURE__*/ new Quaternion()
  4958. const _m1$1 = /*@__PURE__*/ new Matrix4()
  4959. const _target = /*@__PURE__*/ new Vector3()
  4960. const _position$3 = /*@__PURE__*/ new Vector3()
  4961. const _scale$2 = /*@__PURE__*/ new Vector3()
  4962. const _quaternion$2 = /*@__PURE__*/ new Quaternion()
  4963. const _xAxis = /*@__PURE__*/ new Vector3(1, 0, 0)
  4964. const _yAxis = /*@__PURE__*/ new Vector3(0, 1, 0)
  4965. const _zAxis = /*@__PURE__*/ new Vector3(0, 0, 1)
  4966. const _addedEvent = { type: 'added' }
  4967. const _removedEvent = { type: 'removed' }
  4968. class Object3D extends EventDispatcher {
  4969. constructor() {
  4970. super()
  4971. this.isObject3D = true
  4972. Object.defineProperty(this, 'id', { value: _object3DId++ })
  4973. this.uuid = generateUUID()
  4974. this.name = ''
  4975. this.type = 'Object3D'
  4976. this.parent = null
  4977. this.children = []
  4978. this.up = Object3D.DefaultUp.clone()
  4979. const position = new Vector3()
  4980. const rotation = new Euler()
  4981. const quaternion = new Quaternion()
  4982. const scale = new Vector3(1, 1, 1)
  4983. function onRotationChange() {
  4984. quaternion.setFromEuler(rotation, false)
  4985. }
  4986. function onQuaternionChange() {
  4987. rotation.setFromQuaternion(quaternion, undefined, false)
  4988. }
  4989. rotation._onChange(onRotationChange)
  4990. quaternion._onChange(onQuaternionChange)
  4991. Object.defineProperties(this, {
  4992. position: {
  4993. configurable: true,
  4994. enumerable: true,
  4995. value: position
  4996. },
  4997. rotation: {
  4998. configurable: true,
  4999. enumerable: true,
  5000. value: rotation
  5001. },
  5002. quaternion: {
  5003. configurable: true,
  5004. enumerable: true,
  5005. value: quaternion
  5006. },
  5007. scale: {
  5008. configurable: true,
  5009. enumerable: true,
  5010. value: scale
  5011. },
  5012. modelViewMatrix: {
  5013. value: new Matrix4()
  5014. },
  5015. normalMatrix: {
  5016. value: new Matrix3()
  5017. }
  5018. })
  5019. this.matrix = new Matrix4()
  5020. this.matrixWorld = new Matrix4()
  5021. this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate
  5022. this.matrixWorldNeedsUpdate = false
  5023. this.layers = new Layers()
  5024. this.visible = true
  5025. this.castShadow = false
  5026. this.receiveShadow = false
  5027. this.frustumCulled = true
  5028. this.renderOrder = 0
  5029. this.animations = []
  5030. this.userData = {}
  5031. }
  5032. onBeforeRender(/* renderer, scene, camera, geometry, material, group */) {}
  5033. onAfterRender(/* renderer, scene, camera, geometry, material, group */) {}
  5034. applyMatrix4(matrix) {
  5035. if (this.matrixAutoUpdate) this.updateMatrix()
  5036. this.matrix.premultiply(matrix)
  5037. this.matrix.decompose(this.position, this.quaternion, this.scale)
  5038. }
  5039. applyQuaternion(q) {
  5040. this.quaternion.premultiply(q)
  5041. return this
  5042. }
  5043. setRotationFromAxisAngle(axis, angle) {
  5044. // assumes axis is normalized
  5045. this.quaternion.setFromAxisAngle(axis, angle)
  5046. }
  5047. setRotationFromEuler(euler) {
  5048. this.quaternion.setFromEuler(euler, true)
  5049. }
  5050. setRotationFromMatrix(m) {
  5051. // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  5052. this.quaternion.setFromRotationMatrix(m)
  5053. }
  5054. setRotationFromQuaternion(q) {
  5055. // assumes q is normalized
  5056. this.quaternion.copy(q)
  5057. }
  5058. rotateOnAxis(axis, angle) {
  5059. // rotate object on axis in object space
  5060. // axis is assumed to be normalized
  5061. _q1.setFromAxisAngle(axis, angle)
  5062. this.quaternion.multiply(_q1)
  5063. return this
  5064. }
  5065. rotateOnWorldAxis(axis, angle) {
  5066. // rotate object on axis in world space
  5067. // axis is assumed to be normalized
  5068. // method assumes no rotated parent
  5069. _q1.setFromAxisAngle(axis, angle)
  5070. this.quaternion.premultiply(_q1)
  5071. return this
  5072. }
  5073. rotateX(angle) {
  5074. return this.rotateOnAxis(_xAxis, angle)
  5075. }
  5076. rotateY(angle) {
  5077. return this.rotateOnAxis(_yAxis, angle)
  5078. }
  5079. rotateZ(angle) {
  5080. return this.rotateOnAxis(_zAxis, angle)
  5081. }
  5082. translateOnAxis(axis, distance) {
  5083. // translate object by distance along axis in object space
  5084. // axis is assumed to be normalized
  5085. _v1$4.copy(axis).applyQuaternion(this.quaternion)
  5086. this.position.add(_v1$4.multiplyScalar(distance))
  5087. return this
  5088. }
  5089. translateX(distance) {
  5090. return this.translateOnAxis(_xAxis, distance)
  5091. }
  5092. translateY(distance) {
  5093. return this.translateOnAxis(_yAxis, distance)
  5094. }
  5095. translateZ(distance) {
  5096. return this.translateOnAxis(_zAxis, distance)
  5097. }
  5098. localToWorld(vector) {
  5099. return vector.applyMatrix4(this.matrixWorld)
  5100. }
  5101. worldToLocal(vector) {
  5102. return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert())
  5103. }
  5104. lookAt(x, y, z) {
  5105. // This method does not support objects having non-uniformly-scaled parent(s)
  5106. if (x.isVector3) {
  5107. _target.copy(x)
  5108. } else {
  5109. _target.set(x, y, z)
  5110. }
  5111. const parent = this.parent
  5112. this.updateWorldMatrix(true, false)
  5113. _position$3.setFromMatrixPosition(this.matrixWorld)
  5114. if (this.isCamera || this.isLight) {
  5115. _m1$1.lookAt(_position$3, _target, this.up)
  5116. } else {
  5117. _m1$1.lookAt(_target, _position$3, this.up)
  5118. }
  5119. this.quaternion.setFromRotationMatrix(_m1$1)
  5120. if (parent) {
  5121. _m1$1.extractRotation(parent.matrixWorld)
  5122. _q1.setFromRotationMatrix(_m1$1)
  5123. this.quaternion.premultiply(_q1.invert())
  5124. }
  5125. }
  5126. add(object) {
  5127. if (arguments.length > 1) {
  5128. for (let i = 0; i < arguments.length; i++) {
  5129. this.add(arguments[i])
  5130. }
  5131. return this
  5132. }
  5133. if (object === this) {
  5134. console.error("THREE.Object3D.add: object can't be added as a child of itself.", object)
  5135. return this
  5136. }
  5137. if (object && object.isObject3D) {
  5138. if (object.parent !== null) {
  5139. object.parent.remove(object)
  5140. }
  5141. object.parent = this
  5142. this.children.push(object)
  5143. object.dispatchEvent(_addedEvent)
  5144. } else {
  5145. console.error('THREE.Object3D.add: object not an instance of THREE.Object3D.', object)
  5146. }
  5147. return this
  5148. }
  5149. remove(object) {
  5150. if (arguments.length > 1) {
  5151. for (let i = 0; i < arguments.length; i++) {
  5152. this.remove(arguments[i])
  5153. }
  5154. return this
  5155. }
  5156. const index = this.children.indexOf(object)
  5157. if (index !== -1) {
  5158. object.parent = null
  5159. this.children.splice(index, 1)
  5160. object.dispatchEvent(_removedEvent)
  5161. }
  5162. return this
  5163. }
  5164. removeFromParent() {
  5165. const parent = this.parent
  5166. if (parent !== null) {
  5167. parent.remove(this)
  5168. }
  5169. return this
  5170. }
  5171. clear() {
  5172. for (let i = 0; i < this.children.length; i++) {
  5173. const object = this.children[i]
  5174. object.parent = null
  5175. object.dispatchEvent(_removedEvent)
  5176. }
  5177. this.children.length = 0
  5178. return this
  5179. }
  5180. attach(object) {
  5181. // adds object as a child of this, while maintaining the object's world transform
  5182. // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
  5183. this.updateWorldMatrix(true, false)
  5184. _m1$1.copy(this.matrixWorld).invert()
  5185. if (object.parent !== null) {
  5186. object.parent.updateWorldMatrix(true, false)
  5187. _m1$1.multiply(object.parent.matrixWorld)
  5188. }
  5189. object.applyMatrix4(_m1$1)
  5190. this.add(object)
  5191. object.updateWorldMatrix(false, true)
  5192. return this
  5193. }
  5194. getObjectById(id) {
  5195. return this.getObjectByProperty('id', id)
  5196. }
  5197. getObjectByName(name) {
  5198. return this.getObjectByProperty('name', name)
  5199. }
  5200. getObjectByProperty(name, value) {
  5201. if (this[name] === value) return this
  5202. for (let i = 0, l = this.children.length; i < l; i++) {
  5203. const child = this.children[i]
  5204. const object = child.getObjectByProperty(name, value)
  5205. if (object !== undefined) {
  5206. return object
  5207. }
  5208. }
  5209. return undefined
  5210. }
  5211. getWorldPosition(target) {
  5212. this.updateWorldMatrix(true, false)
  5213. return target.setFromMatrixPosition(this.matrixWorld)
  5214. }
  5215. getWorldQuaternion(target) {
  5216. this.updateWorldMatrix(true, false)
  5217. this.matrixWorld.decompose(_position$3, target, _scale$2)
  5218. return target
  5219. }
  5220. getWorldScale(target) {
  5221. this.updateWorldMatrix(true, false)
  5222. this.matrixWorld.decompose(_position$3, _quaternion$2, target)
  5223. return target
  5224. }
  5225. getWorldDirection(target) {
  5226. this.updateWorldMatrix(true, false)
  5227. const e = this.matrixWorld.elements
  5228. return target.set(e[8], e[9], e[10]).normalize()
  5229. }
  5230. raycast(/* raycaster, intersects */) {}
  5231. traverse(callback) {
  5232. callback(this)
  5233. const children = this.children
  5234. for (let i = 0, l = children.length; i < l; i++) {
  5235. children[i].traverse(callback)
  5236. }
  5237. }
  5238. traverseVisible(callback) {
  5239. if (this.visible === false) return
  5240. callback(this)
  5241. const children = this.children
  5242. for (let i = 0, l = children.length; i < l; i++) {
  5243. children[i].traverseVisible(callback)
  5244. }
  5245. }
  5246. traverseAncestors(callback) {
  5247. const parent = this.parent
  5248. if (parent !== null) {
  5249. callback(parent)
  5250. parent.traverseAncestors(callback)
  5251. }
  5252. }
  5253. updateMatrix() {
  5254. this.matrix.compose(this.position, this.quaternion, this.scale)
  5255. this.matrixWorldNeedsUpdate = true
  5256. }
  5257. updateMatrixWorld(force) {
  5258. if (this.matrixAutoUpdate) this.updateMatrix()
  5259. if (this.matrixWorldNeedsUpdate || force) {
  5260. if (this.parent === null) {
  5261. this.matrixWorld.copy(this.matrix)
  5262. } else {
  5263. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix)
  5264. }
  5265. this.matrixWorldNeedsUpdate = false
  5266. force = true
  5267. }
  5268. // update children
  5269. const children = this.children
  5270. for (let i = 0, l = children.length; i < l; i++) {
  5271. children[i].updateMatrixWorld(force)
  5272. }
  5273. }
  5274. updateWorldMatrix(updateParents, updateChildren) {
  5275. const parent = this.parent
  5276. if (updateParents === true && parent !== null) {
  5277. parent.updateWorldMatrix(true, false)
  5278. }
  5279. if (this.matrixAutoUpdate) this.updateMatrix()
  5280. if (this.parent === null) {
  5281. this.matrixWorld.copy(this.matrix)
  5282. } else {
  5283. this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix)
  5284. }
  5285. // update children
  5286. if (updateChildren === true) {
  5287. const children = this.children
  5288. for (let i = 0, l = children.length; i < l; i++) {
  5289. children[i].updateWorldMatrix(false, true)
  5290. }
  5291. }
  5292. }
  5293. toJSON(meta) {
  5294. // meta is a string when called from JSON.stringify
  5295. const isRootObject = meta === undefined || typeof meta === 'string'
  5296. const output = {}
  5297. // meta is a hash used to collect geometries, materials.
  5298. // not providing it implies that this is the root object
  5299. // being serialized.
  5300. if (isRootObject) {
  5301. // initialize meta obj
  5302. meta = {
  5303. geometries: {},
  5304. materials: {},
  5305. textures: {},
  5306. images: {},
  5307. shapes: {},
  5308. skeletons: {},
  5309. animations: {},
  5310. nodes: {}
  5311. }
  5312. output.metadata = {
  5313. version: 4.5,
  5314. type: 'Object',
  5315. generator: 'Object3D.toJSON'
  5316. }
  5317. }
  5318. // standard Object3D serialization
  5319. const object = {}
  5320. object.uuid = this.uuid
  5321. object.type = this.type
  5322. if (this.name !== '') object.name = this.name
  5323. if (this.castShadow === true) object.castShadow = true
  5324. if (this.receiveShadow === true) object.receiveShadow = true
  5325. if (this.visible === false) object.visible = false
  5326. if (this.frustumCulled === false) object.frustumCulled = false
  5327. if (this.renderOrder !== 0) object.renderOrder = this.renderOrder
  5328. if (JSON.stringify(this.userData) !== '{}') object.userData = this.userData
  5329. object.layers = this.layers.mask
  5330. object.matrix = this.matrix.toArray()
  5331. if (this.matrixAutoUpdate === false) object.matrixAutoUpdate = false
  5332. // object specific properties
  5333. if (this.isInstancedMesh) {
  5334. object.type = 'InstancedMesh'
  5335. object.count = this.count
  5336. object.instanceMatrix = this.instanceMatrix.toJSON()
  5337. if (this.instanceColor !== null) object.instanceColor = this.instanceColor.toJSON()
  5338. }
  5339. //
  5340. function serialize(library, element) {
  5341. if (library[element.uuid] === undefined) {
  5342. library[element.uuid] = element.toJSON(meta)
  5343. }
  5344. return element.uuid
  5345. }
  5346. if (this.isScene) {
  5347. if (this.background) {
  5348. if (this.background.isColor) {
  5349. object.background = this.background.toJSON()
  5350. } else if (this.background.isTexture) {
  5351. object.background = this.background.toJSON(meta).uuid
  5352. }
  5353. }
  5354. if (this.environment && this.environment.isTexture) {
  5355. object.environment = this.environment.toJSON(meta).uuid
  5356. }
  5357. } else if (this.isMesh || this.isLine || this.isPoints) {
  5358. object.geometry = serialize(meta.geometries, this.geometry)
  5359. const parameters = this.geometry.parameters
  5360. if (parameters !== undefined && parameters.shapes !== undefined) {
  5361. const shapes = parameters.shapes
  5362. if (Array.isArray(shapes)) {
  5363. for (let i = 0, l = shapes.length; i < l; i++) {
  5364. const shape = shapes[i]
  5365. serialize(meta.shapes, shape)
  5366. }
  5367. } else {
  5368. serialize(meta.shapes, shapes)
  5369. }
  5370. }
  5371. }
  5372. if (this.isSkinnedMesh) {
  5373. object.bindMode = this.bindMode
  5374. object.bindMatrix = this.bindMatrix.toArray()
  5375. if (this.skeleton !== undefined) {
  5376. serialize(meta.skeletons, this.skeleton)
  5377. object.skeleton = this.skeleton.uuid
  5378. }
  5379. }
  5380. if (this.material !== undefined) {
  5381. if (Array.isArray(this.material)) {
  5382. const uuids = []
  5383. for (let i = 0, l = this.material.length; i < l; i++) {
  5384. uuids.push(serialize(meta.materials, this.material[i]))
  5385. }
  5386. object.material = uuids
  5387. } else {
  5388. object.material = serialize(meta.materials, this.material)
  5389. }
  5390. }
  5391. //
  5392. if (this.children.length > 0) {
  5393. object.children = []
  5394. for (let i = 0; i < this.children.length; i++) {
  5395. object.children.push(this.children[i].toJSON(meta).object)
  5396. }
  5397. }
  5398. //
  5399. if (this.animations.length > 0) {
  5400. object.animations = []
  5401. for (let i = 0; i < this.animations.length; i++) {
  5402. const animation = this.animations[i]
  5403. object.animations.push(serialize(meta.animations, animation))
  5404. }
  5405. }
  5406. if (isRootObject) {
  5407. const geometries = extractFromCache(meta.geometries)
  5408. const materials = extractFromCache(meta.materials)
  5409. const textures = extractFromCache(meta.textures)
  5410. const images = extractFromCache(meta.images)
  5411. const shapes = extractFromCache(meta.shapes)
  5412. const skeletons = extractFromCache(meta.skeletons)
  5413. const animations = extractFromCache(meta.animations)
  5414. const nodes = extractFromCache(meta.nodes)
  5415. if (geometries.length > 0) output.geometries = geometries
  5416. if (materials.length > 0) output.materials = materials
  5417. if (textures.length > 0) output.textures = textures
  5418. if (images.length > 0) output.images = images
  5419. if (shapes.length > 0) output.shapes = shapes
  5420. if (skeletons.length > 0) output.skeletons = skeletons
  5421. if (animations.length > 0) output.animations = animations
  5422. if (nodes.length > 0) output.nodes = nodes
  5423. }
  5424. output.object = object
  5425. return output
  5426. // extract data from the cache hash
  5427. // remove metadata on each item
  5428. // and return as array
  5429. function extractFromCache(cache) {
  5430. const values = []
  5431. for (const key in cache) {
  5432. const data = cache[key]
  5433. delete data.metadata
  5434. values.push(data)
  5435. }
  5436. return values
  5437. }
  5438. }
  5439. clone(recursive) {
  5440. return new this.constructor().copy(this, recursive)
  5441. }
  5442. copy(source, recursive = true) {
  5443. this.name = source.name
  5444. this.up.copy(source.up)
  5445. this.position.copy(source.position)
  5446. this.rotation.order = source.rotation.order
  5447. this.quaternion.copy(source.quaternion)
  5448. this.scale.copy(source.scale)
  5449. this.matrix.copy(source.matrix)
  5450. this.matrixWorld.copy(source.matrixWorld)
  5451. this.matrixAutoUpdate = source.matrixAutoUpdate
  5452. this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate
  5453. this.layers.mask = source.layers.mask
  5454. this.visible = source.visible
  5455. this.castShadow = source.castShadow
  5456. this.receiveShadow = source.receiveShadow
  5457. this.frustumCulled = source.frustumCulled
  5458. this.renderOrder = source.renderOrder
  5459. this.userData = JSON.parse(JSON.stringify(source.userData))
  5460. if (recursive === true) {
  5461. for (let i = 0; i < source.children.length; i++) {
  5462. const child = source.children[i]
  5463. this.add(child.clone())
  5464. }
  5465. }
  5466. return this
  5467. }
  5468. }
  5469. Object3D.DefaultUp = new Vector3(0, 1, 0)
  5470. Object3D.DefaultMatrixAutoUpdate = true
  5471. const _v0$1 = /*@__PURE__*/ new Vector3()
  5472. const _v1$3 = /*@__PURE__*/ new Vector3()
  5473. const _v2$2 = /*@__PURE__*/ new Vector3()
  5474. const _v3$1 = /*@__PURE__*/ new Vector3()
  5475. const _vab = /*@__PURE__*/ new Vector3()
  5476. const _vac = /*@__PURE__*/ new Vector3()
  5477. const _vbc = /*@__PURE__*/ new Vector3()
  5478. const _vap = /*@__PURE__*/ new Vector3()
  5479. const _vbp = /*@__PURE__*/ new Vector3()
  5480. const _vcp = /*@__PURE__*/ new Vector3()
  5481. class Triangle {
  5482. constructor(a = new Vector3(), b = new Vector3(), c = new Vector3()) {
  5483. this.a = a
  5484. this.b = b
  5485. this.c = c
  5486. }
  5487. static getNormal(a, b, c, target) {
  5488. target.subVectors(c, b)
  5489. _v0$1.subVectors(a, b)
  5490. target.cross(_v0$1)
  5491. const targetLengthSq = target.lengthSq()
  5492. if (targetLengthSq > 0) {
  5493. return target.multiplyScalar(1 / Math.sqrt(targetLengthSq))
  5494. }
  5495. return target.set(0, 0, 0)
  5496. }
  5497. // static/instance method to calculate barycentric coordinates
  5498. // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
  5499. static getBarycoord(point, a, b, c, target) {
  5500. _v0$1.subVectors(c, a)
  5501. _v1$3.subVectors(b, a)
  5502. _v2$2.subVectors(point, a)
  5503. const dot00 = _v0$1.dot(_v0$1)
  5504. const dot01 = _v0$1.dot(_v1$3)
  5505. const dot02 = _v0$1.dot(_v2$2)
  5506. const dot11 = _v1$3.dot(_v1$3)
  5507. const dot12 = _v1$3.dot(_v2$2)
  5508. const denom = dot00 * dot11 - dot01 * dot01
  5509. // collinear or singular triangle
  5510. if (denom === 0) {
  5511. // arbitrary location outside of triangle?
  5512. // not sure if this is the best idea, maybe should be returning undefined
  5513. return target.set(-2, -1, -1)
  5514. }
  5515. const invDenom = 1 / denom
  5516. const u = (dot11 * dot02 - dot01 * dot12) * invDenom
  5517. const v = (dot00 * dot12 - dot01 * dot02) * invDenom
  5518. // barycentric coordinates must always sum to 1
  5519. return target.set(1 - u - v, v, u)
  5520. }
  5521. static containsPoint(point, a, b, c) {
  5522. this.getBarycoord(point, a, b, c, _v3$1)
  5523. return _v3$1.x >= 0 && _v3$1.y >= 0 && _v3$1.x + _v3$1.y <= 1
  5524. }
  5525. static getUV(point, p1, p2, p3, uv1, uv2, uv3, target) {
  5526. this.getBarycoord(point, p1, p2, p3, _v3$1)
  5527. target.set(0, 0)
  5528. target.addScaledVector(uv1, _v3$1.x)
  5529. target.addScaledVector(uv2, _v3$1.y)
  5530. target.addScaledVector(uv3, _v3$1.z)
  5531. return target
  5532. }
  5533. static isFrontFacing(a, b, c, direction) {
  5534. _v0$1.subVectors(c, b)
  5535. _v1$3.subVectors(a, b)
  5536. // strictly front facing
  5537. return _v0$1.cross(_v1$3).dot(direction) < 0 ? true : false
  5538. }
  5539. set(a, b, c) {
  5540. this.a.copy(a)
  5541. this.b.copy(b)
  5542. this.c.copy(c)
  5543. return this
  5544. }
  5545. setFromPointsAndIndices(points, i0, i1, i2) {
  5546. this.a.copy(points[i0])
  5547. this.b.copy(points[i1])
  5548. this.c.copy(points[i2])
  5549. return this
  5550. }
  5551. setFromAttributeAndIndices(attribute, i0, i1, i2) {
  5552. this.a.fromBufferAttribute(attribute, i0)
  5553. this.b.fromBufferAttribute(attribute, i1)
  5554. this.c.fromBufferAttribute(attribute, i2)
  5555. return this
  5556. }
  5557. clone() {
  5558. return new this.constructor().copy(this)
  5559. }
  5560. copy(triangle) {
  5561. this.a.copy(triangle.a)
  5562. this.b.copy(triangle.b)
  5563. this.c.copy(triangle.c)
  5564. return this
  5565. }
  5566. getArea() {
  5567. _v0$1.subVectors(this.c, this.b)
  5568. _v1$3.subVectors(this.a, this.b)
  5569. return _v0$1.cross(_v1$3).length() * 0.5
  5570. }
  5571. getMidpoint(target) {
  5572. return target
  5573. .addVectors(this.a, this.b)
  5574. .add(this.c)
  5575. .multiplyScalar(1 / 3)
  5576. }
  5577. getNormal(target) {
  5578. return Triangle.getNormal(this.a, this.b, this.c, target)
  5579. }
  5580. getPlane(target) {
  5581. return target.setFromCoplanarPoints(this.a, this.b, this.c)
  5582. }
  5583. getBarycoord(point, target) {
  5584. return Triangle.getBarycoord(point, this.a, this.b, this.c, target)
  5585. }
  5586. getUV(point, uv1, uv2, uv3, target) {
  5587. return Triangle.getUV(point, this.a, this.b, this.c, uv1, uv2, uv3, target)
  5588. }
  5589. containsPoint(point) {
  5590. return Triangle.containsPoint(point, this.a, this.b, this.c)
  5591. }
  5592. isFrontFacing(direction) {
  5593. return Triangle.isFrontFacing(this.a, this.b, this.c, direction)
  5594. }
  5595. intersectsBox(box) {
  5596. return box.intersectsTriangle(this)
  5597. }
  5598. closestPointToPoint(p, target) {
  5599. const a = this.a,
  5600. b = this.b,
  5601. c = this.c
  5602. let v, w
  5603. // algorithm thanks to Real-Time Collision Detection by Christer Ericson,
  5604. // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
  5605. // under the accompanying license; see chapter 5.1.5 for detailed explanation.
  5606. // basically, we're distinguishing which of the voronoi regions of the triangle
  5607. // the point lies in with the minimum amount of redundant computation.
  5608. _vab.subVectors(b, a)
  5609. _vac.subVectors(c, a)
  5610. _vap.subVectors(p, a)
  5611. const d1 = _vab.dot(_vap)
  5612. const d2 = _vac.dot(_vap)
  5613. if (d1 <= 0 && d2 <= 0) {
  5614. // vertex region of A; barycentric coords (1, 0, 0)
  5615. return target.copy(a)
  5616. }
  5617. _vbp.subVectors(p, b)
  5618. const d3 = _vab.dot(_vbp)
  5619. const d4 = _vac.dot(_vbp)
  5620. if (d3 >= 0 && d4 <= d3) {
  5621. // vertex region of B; barycentric coords (0, 1, 0)
  5622. return target.copy(b)
  5623. }
  5624. const vc = d1 * d4 - d3 * d2
  5625. if (vc <= 0 && d1 >= 0 && d3 <= 0) {
  5626. v = d1 / (d1 - d3)
  5627. // edge region of AB; barycentric coords (1-v, v, 0)
  5628. return target.copy(a).addScaledVector(_vab, v)
  5629. }
  5630. _vcp.subVectors(p, c)
  5631. const d5 = _vab.dot(_vcp)
  5632. const d6 = _vac.dot(_vcp)
  5633. if (d6 >= 0 && d5 <= d6) {
  5634. // vertex region of C; barycentric coords (0, 0, 1)
  5635. return target.copy(c)
  5636. }
  5637. const vb = d5 * d2 - d1 * d6
  5638. if (vb <= 0 && d2 >= 0 && d6 <= 0) {
  5639. w = d2 / (d2 - d6)
  5640. // edge region of AC; barycentric coords (1-w, 0, w)
  5641. return target.copy(a).addScaledVector(_vac, w)
  5642. }
  5643. const va = d3 * d6 - d5 * d4
  5644. if (va <= 0 && d4 - d3 >= 0 && d5 - d6 >= 0) {
  5645. _vbc.subVectors(c, b)
  5646. w = (d4 - d3) / (d4 - d3 + (d5 - d6))
  5647. // edge region of BC; barycentric coords (0, 1-w, w)
  5648. return target.copy(b).addScaledVector(_vbc, w) // edge region of BC
  5649. }
  5650. // face region
  5651. const denom = 1 / (va + vb + vc)
  5652. // u = va * denom
  5653. v = vb * denom
  5654. w = vc * denom
  5655. return target
  5656. .copy(a)
  5657. .addScaledVector(_vab, v)
  5658. .addScaledVector(_vac, w)
  5659. }
  5660. equals(triangle) {
  5661. return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c)
  5662. }
  5663. }
  5664. let materialId = 0
  5665. class Material extends EventDispatcher {
  5666. constructor() {
  5667. super()
  5668. this.isMaterial = true
  5669. Object.defineProperty(this, 'id', { value: materialId++ })
  5670. this.uuid = generateUUID()
  5671. this.name = ''
  5672. this.type = 'Material'
  5673. this.blending = NormalBlending
  5674. this.side = FrontSide
  5675. this.vertexColors = false
  5676. this.opacity = 1
  5677. this.transparent = false
  5678. this.blendSrc = SrcAlphaFactor
  5679. this.blendDst = OneMinusSrcAlphaFactor
  5680. this.blendEquation = AddEquation
  5681. this.blendSrcAlpha = null
  5682. this.blendDstAlpha = null
  5683. this.blendEquationAlpha = null
  5684. this.depthFunc = LessEqualDepth
  5685. this.depthTest = true
  5686. this.depthWrite = true
  5687. this.stencilWriteMask = 0xff
  5688. this.stencilFunc = AlwaysStencilFunc
  5689. this.stencilRef = 0
  5690. this.stencilFuncMask = 0xff
  5691. this.stencilFail = KeepStencilOp
  5692. this.stencilZFail = KeepStencilOp
  5693. this.stencilZPass = KeepStencilOp
  5694. this.stencilWrite = false
  5695. this.clippingPlanes = null
  5696. this.clipIntersection = false
  5697. this.clipShadows = false
  5698. this.shadowSide = null
  5699. this.colorWrite = true
  5700. this.precision = null // override the renderer's default precision for this material
  5701. this.polygonOffset = false
  5702. this.polygonOffsetFactor = 0
  5703. this.polygonOffsetUnits = 0
  5704. this.dithering = false
  5705. this.alphaToCoverage = false
  5706. this.premultipliedAlpha = false
  5707. this.visible = true
  5708. this.toneMapped = true
  5709. this.userData = {}
  5710. this.version = 0
  5711. this._alphaTest = 0
  5712. }
  5713. get alphaTest() {
  5714. return this._alphaTest
  5715. }
  5716. set alphaTest(value) {
  5717. if (this._alphaTest > 0 !== value > 0) {
  5718. this.version++
  5719. }
  5720. this._alphaTest = value
  5721. }
  5722. onBuild(/* shaderobject, renderer */) {}
  5723. onBeforeRender(/* renderer, scene, camera, geometry, object, group */) {}
  5724. onBeforeCompile(/* shaderobject, renderer */) {}
  5725. customProgramCacheKey() {
  5726. return this.onBeforeCompile.toString()
  5727. }
  5728. setValues(values) {
  5729. if (values === undefined) return
  5730. for (const key in values) {
  5731. const newValue = values[key]
  5732. if (newValue === undefined) {
  5733. console.warn("THREE.Material: '" + key + "' parameter is undefined.")
  5734. continue
  5735. }
  5736. // for backward compatibility if shading is set in the constructor
  5737. if (key === 'shading') {
  5738. console.warn('THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.')
  5739. this.flatShading = newValue === FlatShading ? true : false
  5740. continue
  5741. }
  5742. const currentValue = this[key]
  5743. if (currentValue === undefined) {
  5744. console.warn('THREE.' + this.type + ": '" + key + "' is not a property of this material.")
  5745. continue
  5746. }
  5747. if (currentValue && currentValue.isColor) {
  5748. currentValue.set(newValue)
  5749. } else if (currentValue && currentValue.isVector3 && newValue && newValue.isVector3) {
  5750. currentValue.copy(newValue)
  5751. } else {
  5752. this[key] = newValue
  5753. }
  5754. }
  5755. }
  5756. toJSON(meta) {
  5757. const isRootObject = meta === undefined || typeof meta === 'string'
  5758. if (isRootObject) {
  5759. meta = {
  5760. textures: {},
  5761. images: {}
  5762. }
  5763. }
  5764. const data = {
  5765. metadata: {
  5766. version: 4.5,
  5767. type: 'Material',
  5768. generator: 'Material.toJSON'
  5769. }
  5770. }
  5771. // standard Material serialization
  5772. data.uuid = this.uuid
  5773. data.type = this.type
  5774. if (this.name !== '') data.name = this.name
  5775. if (this.color && this.color.isColor) data.color = this.color.getHex()
  5776. if (this.roughness !== undefined) data.roughness = this.roughness
  5777. if (this.metalness !== undefined) data.metalness = this.metalness
  5778. if (this.sheen !== undefined) data.sheen = this.sheen
  5779. if (this.sheenColor && this.sheenColor.isColor) data.sheenColor = this.sheenColor.getHex()
  5780. if (this.sheenRoughness !== undefined) data.sheenRoughness = this.sheenRoughness
  5781. if (this.emissive && this.emissive.isColor) data.emissive = this.emissive.getHex()
  5782. if (this.emissiveIntensity && this.emissiveIntensity !== 1) data.emissiveIntensity = this.emissiveIntensity
  5783. if (this.specular && this.specular.isColor) data.specular = this.specular.getHex()
  5784. if (this.specularIntensity !== undefined) data.specularIntensity = this.specularIntensity
  5785. if (this.specularColor && this.specularColor.isColor) data.specularColor = this.specularColor.getHex()
  5786. if (this.shininess !== undefined) data.shininess = this.shininess
  5787. if (this.clearcoat !== undefined) data.clearcoat = this.clearcoat
  5788. if (this.clearcoatRoughness !== undefined) data.clearcoatRoughness = this.clearcoatRoughness
  5789. if (this.clearcoatMap && this.clearcoatMap.isTexture) {
  5790. data.clearcoatMap = this.clearcoatMap.toJSON(meta).uuid
  5791. }
  5792. if (this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture) {
  5793. data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON(meta).uuid
  5794. }
  5795. if (this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture) {
  5796. data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON(meta).uuid
  5797. data.clearcoatNormalScale = this.clearcoatNormalScale.toArray()
  5798. }
  5799. if (this.iridescence !== undefined) data.iridescence = this.iridescence
  5800. if (this.iridescenceIOR !== undefined) data.iridescenceIOR = this.iridescenceIOR
  5801. if (this.iridescenceThicknessRange !== undefined) data.iridescenceThicknessRange = this.iridescenceThicknessRange
  5802. if (this.iridescenceMap && this.iridescenceMap.isTexture) {
  5803. data.iridescenceMap = this.iridescenceMap.toJSON(meta).uuid
  5804. }
  5805. if (this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture) {
  5806. data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON(meta).uuid
  5807. }
  5808. if (this.map && this.map.isTexture) data.map = this.map.toJSON(meta).uuid
  5809. if (this.matcap && this.matcap.isTexture) data.matcap = this.matcap.toJSON(meta).uuid
  5810. if (this.alphaMap && this.alphaMap.isTexture) data.alphaMap = this.alphaMap.toJSON(meta).uuid
  5811. if (this.lightMap && this.lightMap.isTexture) {
  5812. data.lightMap = this.lightMap.toJSON(meta).uuid
  5813. data.lightMapIntensity = this.lightMapIntensity
  5814. }
  5815. if (this.aoMap && this.aoMap.isTexture) {
  5816. data.aoMap = this.aoMap.toJSON(meta).uuid
  5817. data.aoMapIntensity = this.aoMapIntensity
  5818. }
  5819. if (this.bumpMap && this.bumpMap.isTexture) {
  5820. data.bumpMap = this.bumpMap.toJSON(meta).uuid
  5821. data.bumpScale = this.bumpScale
  5822. }
  5823. if (this.normalMap && this.normalMap.isTexture) {
  5824. data.normalMap = this.normalMap.toJSON(meta).uuid
  5825. data.normalMapType = this.normalMapType
  5826. data.normalScale = this.normalScale.toArray()
  5827. }
  5828. if (this.displacementMap && this.displacementMap.isTexture) {
  5829. data.displacementMap = this.displacementMap.toJSON(meta).uuid
  5830. data.displacementScale = this.displacementScale
  5831. data.displacementBias = this.displacementBias
  5832. }
  5833. if (this.roughnessMap && this.roughnessMap.isTexture) data.roughnessMap = this.roughnessMap.toJSON(meta).uuid
  5834. if (this.metalnessMap && this.metalnessMap.isTexture) data.metalnessMap = this.metalnessMap.toJSON(meta).uuid
  5835. if (this.emissiveMap && this.emissiveMap.isTexture) data.emissiveMap = this.emissiveMap.toJSON(meta).uuid
  5836. if (this.specularMap && this.specularMap.isTexture) data.specularMap = this.specularMap.toJSON(meta).uuid
  5837. if (this.specularIntensityMap && this.specularIntensityMap.isTexture) data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid
  5838. if (this.specularColorMap && this.specularColorMap.isTexture) data.specularColorMap = this.specularColorMap.toJSON(meta).uuid
  5839. if (this.envMap && this.envMap.isTexture) {
  5840. data.envMap = this.envMap.toJSON(meta).uuid
  5841. if (this.combine !== undefined) data.combine = this.combine
  5842. }
  5843. if (this.envMapIntensity !== undefined) data.envMapIntensity = this.envMapIntensity
  5844. if (this.reflectivity !== undefined) data.reflectivity = this.reflectivity
  5845. if (this.refractionRatio !== undefined) data.refractionRatio = this.refractionRatio
  5846. if (this.gradientMap && this.gradientMap.isTexture) {
  5847. data.gradientMap = this.gradientMap.toJSON(meta).uuid
  5848. }
  5849. if (this.transmission !== undefined) data.transmission = this.transmission
  5850. if (this.transmissionMap && this.transmissionMap.isTexture) data.transmissionMap = this.transmissionMap.toJSON(meta).uuid
  5851. if (this.thickness !== undefined) data.thickness = this.thickness
  5852. if (this.thicknessMap && this.thicknessMap.isTexture) data.thicknessMap = this.thicknessMap.toJSON(meta).uuid
  5853. if (this.attenuationDistance !== undefined) data.attenuationDistance = this.attenuationDistance
  5854. if (this.attenuationColor !== undefined) data.attenuationColor = this.attenuationColor.getHex()
  5855. if (this.size !== undefined) data.size = this.size
  5856. if (this.shadowSide !== null) data.shadowSide = this.shadowSide
  5857. if (this.sizeAttenuation !== undefined) data.sizeAttenuation = this.sizeAttenuation
  5858. if (this.blending !== NormalBlending) data.blending = this.blending
  5859. if (this.side !== FrontSide) data.side = this.side
  5860. if (this.vertexColors) data.vertexColors = true
  5861. if (this.opacity < 1) data.opacity = this.opacity
  5862. if (this.transparent === true) data.transparent = this.transparent
  5863. data.depthFunc = this.depthFunc
  5864. data.depthTest = this.depthTest
  5865. data.depthWrite = this.depthWrite
  5866. data.colorWrite = this.colorWrite
  5867. data.stencilWrite = this.stencilWrite
  5868. data.stencilWriteMask = this.stencilWriteMask
  5869. data.stencilFunc = this.stencilFunc
  5870. data.stencilRef = this.stencilRef
  5871. data.stencilFuncMask = this.stencilFuncMask
  5872. data.stencilFail = this.stencilFail
  5873. data.stencilZFail = this.stencilZFail
  5874. data.stencilZPass = this.stencilZPass
  5875. // rotation (SpriteMaterial)
  5876. if (this.rotation !== undefined && this.rotation !== 0) data.rotation = this.rotation
  5877. if (this.polygonOffset === true) data.polygonOffset = true
  5878. if (this.polygonOffsetFactor !== 0) data.polygonOffsetFactor = this.polygonOffsetFactor
  5879. if (this.polygonOffsetUnits !== 0) data.polygonOffsetUnits = this.polygonOffsetUnits
  5880. if (this.linewidth !== undefined && this.linewidth !== 1) data.linewidth = this.linewidth
  5881. if (this.dashSize !== undefined) data.dashSize = this.dashSize
  5882. if (this.gapSize !== undefined) data.gapSize = this.gapSize
  5883. if (this.scale !== undefined) data.scale = this.scale
  5884. if (this.dithering === true) data.dithering = true
  5885. if (this.alphaTest > 0) data.alphaTest = this.alphaTest
  5886. if (this.alphaToCoverage === true) data.alphaToCoverage = this.alphaToCoverage
  5887. if (this.premultipliedAlpha === true) data.premultipliedAlpha = this.premultipliedAlpha
  5888. if (this.wireframe === true) data.wireframe = this.wireframe
  5889. if (this.wireframeLinewidth > 1) data.wireframeLinewidth = this.wireframeLinewidth
  5890. if (this.wireframeLinecap !== 'round') data.wireframeLinecap = this.wireframeLinecap
  5891. if (this.wireframeLinejoin !== 'round') data.wireframeLinejoin = this.wireframeLinejoin
  5892. if (this.flatShading === true) data.flatShading = this.flatShading
  5893. if (this.visible === false) data.visible = false
  5894. if (this.toneMapped === false) data.toneMapped = false
  5895. if (this.fog === false) data.fog = false
  5896. if (JSON.stringify(this.userData) !== '{}') data.userData = this.userData
  5897. // TODO: Copied from Object3D.toJSON
  5898. function extractFromCache(cache) {
  5899. const values = []
  5900. for (const key in cache) {
  5901. const data = cache[key]
  5902. delete data.metadata
  5903. values.push(data)
  5904. }
  5905. return values
  5906. }
  5907. if (isRootObject) {
  5908. const textures = extractFromCache(meta.textures)
  5909. const images = extractFromCache(meta.images)
  5910. if (textures.length > 0) data.textures = textures
  5911. if (images.length > 0) data.images = images
  5912. }
  5913. return data
  5914. }
  5915. clone() {
  5916. return new this.constructor().copy(this)
  5917. }
  5918. copy(source) {
  5919. this.name = source.name
  5920. this.blending = source.blending
  5921. this.side = source.side
  5922. this.vertexColors = source.vertexColors
  5923. this.opacity = source.opacity
  5924. this.transparent = source.transparent
  5925. this.blendSrc = source.blendSrc
  5926. this.blendDst = source.blendDst
  5927. this.blendEquation = source.blendEquation
  5928. this.blendSrcAlpha = source.blendSrcAlpha
  5929. this.blendDstAlpha = source.blendDstAlpha
  5930. this.blendEquationAlpha = source.blendEquationAlpha
  5931. this.depthFunc = source.depthFunc
  5932. this.depthTest = source.depthTest
  5933. this.depthWrite = source.depthWrite
  5934. this.stencilWriteMask = source.stencilWriteMask
  5935. this.stencilFunc = source.stencilFunc
  5936. this.stencilRef = source.stencilRef
  5937. this.stencilFuncMask = source.stencilFuncMask
  5938. this.stencilFail = source.stencilFail
  5939. this.stencilZFail = source.stencilZFail
  5940. this.stencilZPass = source.stencilZPass
  5941. this.stencilWrite = source.stencilWrite
  5942. const srcPlanes = source.clippingPlanes
  5943. let dstPlanes = null
  5944. if (srcPlanes !== null) {
  5945. const n = srcPlanes.length
  5946. dstPlanes = new Array(n)
  5947. for (let i = 0; i !== n; ++i) {
  5948. dstPlanes[i] = srcPlanes[i].clone()
  5949. }
  5950. }
  5951. this.clippingPlanes = dstPlanes
  5952. this.clipIntersection = source.clipIntersection
  5953. this.clipShadows = source.clipShadows
  5954. this.shadowSide = source.shadowSide
  5955. this.colorWrite = source.colorWrite
  5956. this.precision = source.precision
  5957. this.polygonOffset = source.polygonOffset
  5958. this.polygonOffsetFactor = source.polygonOffsetFactor
  5959. this.polygonOffsetUnits = source.polygonOffsetUnits
  5960. this.dithering = source.dithering
  5961. this.alphaTest = source.alphaTest
  5962. this.alphaToCoverage = source.alphaToCoverage
  5963. this.premultipliedAlpha = source.premultipliedAlpha
  5964. this.visible = source.visible
  5965. this.toneMapped = source.toneMapped
  5966. this.userData = JSON.parse(JSON.stringify(source.userData))
  5967. return this
  5968. }
  5969. dispose() {
  5970. this.dispatchEvent({ type: 'dispose' })
  5971. }
  5972. set needsUpdate(value) {
  5973. if (value === true) this.version++
  5974. }
  5975. // @deprecated since r131, f5803c62cc4a29d90744e9dc7811d086e354c1d8
  5976. get vertexTangents() {
  5977. console.warn('THREE.' + this.type + ': .vertexTangents has been removed.')
  5978. return false
  5979. }
  5980. set vertexTangents(value) {
  5981. console.warn('THREE.' + this.type + ': .vertexTangents has been removed.')
  5982. }
  5983. }
  5984. Material.fromType = function(/*type*/) {
  5985. // TODO: Behavior added in Materials.js
  5986. return null
  5987. }
  5988. class MeshBasicMaterial extends Material {
  5989. constructor(parameters) {
  5990. super()
  5991. this.isMeshBasicMaterial = true
  5992. this.type = 'MeshBasicMaterial'
  5993. this.color = new Color(0xffffff) // emissive
  5994. this.map = null
  5995. this.lightMap = null
  5996. this.lightMapIntensity = 1.0
  5997. this.aoMap = null
  5998. this.aoMapIntensity = 1.0
  5999. this.specularMap = null
  6000. this.alphaMap = null
  6001. this.envMap = null
  6002. this.combine = MultiplyOperation
  6003. this.reflectivity = 1
  6004. this.refractionRatio = 0.98
  6005. this.wireframe = false
  6006. this.wireframeLinewidth = 1
  6007. this.wireframeLinecap = 'round'
  6008. this.wireframeLinejoin = 'round'
  6009. this.fog = true
  6010. this.setValues(parameters)
  6011. }
  6012. copy(source) {
  6013. super.copy(source)
  6014. this.color.copy(source.color)
  6015. this.map = source.map
  6016. this.lightMap = source.lightMap
  6017. this.lightMapIntensity = source.lightMapIntensity
  6018. this.aoMap = source.aoMap
  6019. this.aoMapIntensity = source.aoMapIntensity
  6020. this.specularMap = source.specularMap
  6021. this.alphaMap = source.alphaMap
  6022. this.envMap = source.envMap
  6023. this.combine = source.combine
  6024. this.reflectivity = source.reflectivity
  6025. this.refractionRatio = source.refractionRatio
  6026. this.wireframe = source.wireframe
  6027. this.wireframeLinewidth = source.wireframeLinewidth
  6028. this.wireframeLinecap = source.wireframeLinecap
  6029. this.wireframeLinejoin = source.wireframeLinejoin
  6030. this.fog = source.fog
  6031. return this
  6032. }
  6033. }
  6034. const _vector$9 = /*@__PURE__*/ new Vector3()
  6035. const _vector2$1 = /*@__PURE__*/ new Vector2()
  6036. class BufferAttribute {
  6037. constructor(array, itemSize, normalized) {
  6038. if (Array.isArray(array)) {
  6039. throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.')
  6040. }
  6041. this.isBufferAttribute = true
  6042. this.name = ''
  6043. this.array = array
  6044. this.itemSize = itemSize
  6045. this.count = array !== undefined ? array.length / itemSize : 0
  6046. this.normalized = normalized === true
  6047. this.usage = StaticDrawUsage
  6048. this.updateRange = { offset: 0, count: -1 }
  6049. this.version = 0
  6050. }
  6051. onUploadCallback() {}
  6052. set needsUpdate(value) {
  6053. if (value === true) this.version++
  6054. }
  6055. setUsage(value) {
  6056. this.usage = value
  6057. return this
  6058. }
  6059. copy(source) {
  6060. this.name = source.name
  6061. this.array = new source.array.constructor(source.array)
  6062. this.itemSize = source.itemSize
  6063. this.count = source.count
  6064. this.normalized = source.normalized
  6065. this.usage = source.usage
  6066. return this
  6067. }
  6068. copyAt(index1, attribute, index2) {
  6069. index1 *= this.itemSize
  6070. index2 *= attribute.itemSize
  6071. for (let i = 0, l = this.itemSize; i < l; i++) {
  6072. this.array[index1 + i] = attribute.array[index2 + i]
  6073. }
  6074. return this
  6075. }
  6076. copyArray(array) {
  6077. this.array.set(array)
  6078. return this
  6079. }
  6080. copyColorsArray(colors) {
  6081. const array = this.array
  6082. let offset = 0
  6083. for (let i = 0, l = colors.length; i < l; i++) {
  6084. let color = colors[i]
  6085. if (color === undefined) {
  6086. console.warn('THREE.BufferAttribute.copyColorsArray(): color is undefined', i)
  6087. color = new Color()
  6088. }
  6089. array[offset++] = color.r
  6090. array[offset++] = color.g
  6091. array[offset++] = color.b
  6092. }
  6093. return this
  6094. }
  6095. copyVector2sArray(vectors) {
  6096. const array = this.array
  6097. let offset = 0
  6098. for (let i = 0, l = vectors.length; i < l; i++) {
  6099. let vector = vectors[i]
  6100. if (vector === undefined) {
  6101. console.warn('THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i)
  6102. vector = new Vector2()
  6103. }
  6104. array[offset++] = vector.x
  6105. array[offset++] = vector.y
  6106. }
  6107. return this
  6108. }
  6109. copyVector3sArray(vectors) {
  6110. const array = this.array
  6111. let offset = 0
  6112. for (let i = 0, l = vectors.length; i < l; i++) {
  6113. let vector = vectors[i]
  6114. if (vector === undefined) {
  6115. console.warn('THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i)
  6116. vector = new Vector3()
  6117. }
  6118. array[offset++] = vector.x
  6119. array[offset++] = vector.y
  6120. array[offset++] = vector.z
  6121. }
  6122. return this
  6123. }
  6124. copyVector4sArray(vectors) {
  6125. const array = this.array
  6126. let offset = 0
  6127. for (let i = 0, l = vectors.length; i < l; i++) {
  6128. let vector = vectors[i]
  6129. if (vector === undefined) {
  6130. console.warn('THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i)
  6131. vector = new Vector4()
  6132. }
  6133. array[offset++] = vector.x
  6134. array[offset++] = vector.y
  6135. array[offset++] = vector.z
  6136. array[offset++] = vector.w
  6137. }
  6138. return this
  6139. }
  6140. applyMatrix3(m) {
  6141. if (this.itemSize === 2) {
  6142. for (let i = 0, l = this.count; i < l; i++) {
  6143. _vector2$1.fromBufferAttribute(this, i)
  6144. _vector2$1.applyMatrix3(m)
  6145. this.setXY(i, _vector2$1.x, _vector2$1.y)
  6146. }
  6147. } else if (this.itemSize === 3) {
  6148. for (let i = 0, l = this.count; i < l; i++) {
  6149. _vector$9.fromBufferAttribute(this, i)
  6150. _vector$9.applyMatrix3(m)
  6151. this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z)
  6152. }
  6153. }
  6154. return this
  6155. }
  6156. applyMatrix4(m) {
  6157. for (let i = 0, l = this.count; i < l; i++) {
  6158. _vector$9.fromBufferAttribute(this, i)
  6159. _vector$9.applyMatrix4(m)
  6160. this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z)
  6161. }
  6162. return this
  6163. }
  6164. applyNormalMatrix(m) {
  6165. for (let i = 0, l = this.count; i < l; i++) {
  6166. _vector$9.fromBufferAttribute(this, i)
  6167. _vector$9.applyNormalMatrix(m)
  6168. this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z)
  6169. }
  6170. return this
  6171. }
  6172. transformDirection(m) {
  6173. for (let i = 0, l = this.count; i < l; i++) {
  6174. _vector$9.fromBufferAttribute(this, i)
  6175. _vector$9.transformDirection(m)
  6176. this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z)
  6177. }
  6178. return this
  6179. }
  6180. set(value, offset = 0) {
  6181. this.array.set(value, offset)
  6182. return this
  6183. }
  6184. getX(index) {
  6185. return this.array[index * this.itemSize]
  6186. }
  6187. setX(index, x) {
  6188. this.array[index * this.itemSize] = x
  6189. return this
  6190. }
  6191. getY(index) {
  6192. return this.array[index * this.itemSize + 1]
  6193. }
  6194. setY(index, y) {
  6195. this.array[index * this.itemSize + 1] = y
  6196. return this
  6197. }
  6198. getZ(index) {
  6199. return this.array[index * this.itemSize + 2]
  6200. }
  6201. setZ(index, z) {
  6202. this.array[index * this.itemSize + 2] = z
  6203. return this
  6204. }
  6205. getW(index) {
  6206. return this.array[index * this.itemSize + 3]
  6207. }
  6208. setW(index, w) {
  6209. this.array[index * this.itemSize + 3] = w
  6210. return this
  6211. }
  6212. setXY(index, x, y) {
  6213. index *= this.itemSize
  6214. this.array[index + 0] = x
  6215. this.array[index + 1] = y
  6216. return this
  6217. }
  6218. setXYZ(index, x, y, z) {
  6219. index *= this.itemSize
  6220. this.array[index + 0] = x
  6221. this.array[index + 1] = y
  6222. this.array[index + 2] = z
  6223. return this
  6224. }
  6225. setXYZW(index, x, y, z, w) {
  6226. index *= this.itemSize
  6227. this.array[index + 0] = x
  6228. this.array[index + 1] = y
  6229. this.array[index + 2] = z
  6230. this.array[index + 3] = w
  6231. return this
  6232. }
  6233. onUpload(callback) {
  6234. this.onUploadCallback = callback
  6235. return this
  6236. }
  6237. clone() {
  6238. return new this.constructor(this.array, this.itemSize).copy(this)
  6239. }
  6240. toJSON() {
  6241. const data = {
  6242. itemSize: this.itemSize,
  6243. type: this.array.constructor.name,
  6244. array: Array.prototype.slice.call(this.array),
  6245. normalized: this.normalized
  6246. }
  6247. if (this.name !== '') data.name = this.name
  6248. if (this.usage !== StaticDrawUsage) data.usage = this.usage
  6249. if (this.updateRange.offset !== 0 || this.updateRange.count !== -1) data.updateRange = this.updateRange
  6250. return data
  6251. }
  6252. }
  6253. //
  6254. class Int8BufferAttribute extends BufferAttribute {
  6255. constructor(array, itemSize, normalized) {
  6256. super(new Int8Array(array), itemSize, normalized)
  6257. }
  6258. }
  6259. class Uint8BufferAttribute extends BufferAttribute {
  6260. constructor(array, itemSize, normalized) {
  6261. super(new Uint8Array(array), itemSize, normalized)
  6262. }
  6263. }
  6264. class Uint8ClampedBufferAttribute extends BufferAttribute {
  6265. constructor(array, itemSize, normalized) {
  6266. super(new Uint8ClampedArray(array), itemSize, normalized)
  6267. }
  6268. }
  6269. class Int16BufferAttribute extends BufferAttribute {
  6270. constructor(array, itemSize, normalized) {
  6271. super(new Int16Array(array), itemSize, normalized)
  6272. }
  6273. }
  6274. class Uint16BufferAttribute extends BufferAttribute {
  6275. constructor(array, itemSize, normalized) {
  6276. super(new Uint16Array(array), itemSize, normalized)
  6277. }
  6278. }
  6279. class Int32BufferAttribute extends BufferAttribute {
  6280. constructor(array, itemSize, normalized) {
  6281. super(new Int32Array(array), itemSize, normalized)
  6282. }
  6283. }
  6284. class Uint32BufferAttribute extends BufferAttribute {
  6285. constructor(array, itemSize, normalized) {
  6286. super(new Uint32Array(array), itemSize, normalized)
  6287. }
  6288. }
  6289. class Float16BufferAttribute extends BufferAttribute {
  6290. constructor(array, itemSize, normalized) {
  6291. super(new Uint16Array(array), itemSize, normalized)
  6292. this.isFloat16BufferAttribute = true
  6293. }
  6294. }
  6295. class Float32BufferAttribute extends BufferAttribute {
  6296. constructor(array, itemSize, normalized) {
  6297. super(new Float32Array(array), itemSize, normalized)
  6298. }
  6299. }
  6300. class Float64BufferAttribute extends BufferAttribute {
  6301. constructor(array, itemSize, normalized) {
  6302. super(new Float64Array(array), itemSize, normalized)
  6303. }
  6304. }
  6305. let _id$1 = 0
  6306. const _m1 = /*@__PURE__*/ new Matrix4()
  6307. const _obj = /*@__PURE__*/ new Object3D()
  6308. const _offset = /*@__PURE__*/ new Vector3()
  6309. const _box$1 = /*@__PURE__*/ new Box3()
  6310. const _boxMorphTargets = /*@__PURE__*/ new Box3()
  6311. const _vector$8 = /*@__PURE__*/ new Vector3()
  6312. class BufferGeometry extends EventDispatcher {
  6313. constructor() {
  6314. super()
  6315. this.isBufferGeometry = true
  6316. Object.defineProperty(this, 'id', { value: _id$1++ })
  6317. this.uuid = generateUUID()
  6318. this.name = ''
  6319. this.type = 'BufferGeometry'
  6320. this.index = null
  6321. this.attributes = {}
  6322. this.morphAttributes = {}
  6323. this.morphTargetsRelative = false
  6324. this.groups = []
  6325. this.boundingBox = null
  6326. this.boundingSphere = null
  6327. this.drawRange = { start: 0, count: Infinity }
  6328. this.userData = {}
  6329. }
  6330. getIndex() {
  6331. return this.index
  6332. }
  6333. setIndex(index) {
  6334. if (Array.isArray(index)) {
  6335. this.index = new (arrayNeedsUint32(index) ? Uint32BufferAttribute : Uint16BufferAttribute)(index, 1)
  6336. } else {
  6337. this.index = index
  6338. }
  6339. return this
  6340. }
  6341. getAttribute(name) {
  6342. return this.attributes[name]
  6343. }
  6344. setAttribute(name, attribute) {
  6345. this.attributes[name] = attribute
  6346. return this
  6347. }
  6348. deleteAttribute(name) {
  6349. delete this.attributes[name]
  6350. return this
  6351. }
  6352. hasAttribute(name) {
  6353. return this.attributes[name] !== undefined
  6354. }
  6355. addGroup(start, count, materialIndex = 0) {
  6356. this.groups.push({
  6357. start: start,
  6358. count: count,
  6359. materialIndex: materialIndex
  6360. })
  6361. }
  6362. clearGroups() {
  6363. this.groups = []
  6364. }
  6365. setDrawRange(start, count) {
  6366. this.drawRange.start = start
  6367. this.drawRange.count = count
  6368. }
  6369. applyMatrix4(matrix) {
  6370. const position = this.attributes.position
  6371. if (position !== undefined) {
  6372. position.applyMatrix4(matrix)
  6373. position.needsUpdate = true
  6374. }
  6375. const normal = this.attributes.normal
  6376. if (normal !== undefined) {
  6377. const normalMatrix = new Matrix3().getNormalMatrix(matrix)
  6378. normal.applyNormalMatrix(normalMatrix)
  6379. normal.needsUpdate = true
  6380. }
  6381. const tangent = this.attributes.tangent
  6382. if (tangent !== undefined) {
  6383. tangent.transformDirection(matrix)
  6384. tangent.needsUpdate = true
  6385. }
  6386. if (this.boundingBox !== null) {
  6387. this.computeBoundingBox()
  6388. }
  6389. if (this.boundingSphere !== null) {
  6390. this.computeBoundingSphere()
  6391. }
  6392. return this
  6393. }
  6394. applyQuaternion(q) {
  6395. _m1.makeRotationFromQuaternion(q)
  6396. this.applyMatrix4(_m1)
  6397. return this
  6398. }
  6399. rotateX(angle) {
  6400. // rotate geometry around world x-axis
  6401. _m1.makeRotationX(angle)
  6402. this.applyMatrix4(_m1)
  6403. return this
  6404. }
  6405. rotateY(angle) {
  6406. // rotate geometry around world y-axis
  6407. _m1.makeRotationY(angle)
  6408. this.applyMatrix4(_m1)
  6409. return this
  6410. }
  6411. rotateZ(angle) {
  6412. // rotate geometry around world z-axis
  6413. _m1.makeRotationZ(angle)
  6414. this.applyMatrix4(_m1)
  6415. return this
  6416. }
  6417. translate(x, y, z) {
  6418. // translate geometry
  6419. _m1.makeTranslation(x, y, z)
  6420. this.applyMatrix4(_m1)
  6421. return this
  6422. }
  6423. scale(x, y, z) {
  6424. // scale geometry
  6425. _m1.makeScale(x, y, z)
  6426. this.applyMatrix4(_m1)
  6427. return this
  6428. }
  6429. lookAt(vector) {
  6430. _obj.lookAt(vector)
  6431. _obj.updateMatrix()
  6432. this.applyMatrix4(_obj.matrix)
  6433. return this
  6434. }
  6435. center() {
  6436. this.computeBoundingBox()
  6437. this.boundingBox.getCenter(_offset).negate()
  6438. this.translate(_offset.x, _offset.y, _offset.z)
  6439. return this
  6440. }
  6441. setFromPoints(points) {
  6442. const position = []
  6443. for (let i = 0, l = points.length; i < l; i++) {
  6444. const point = points[i]
  6445. position.push(point.x, point.y, point.z || 0)
  6446. }
  6447. this.setAttribute('position', new Float32BufferAttribute(position, 3))
  6448. return this
  6449. }
  6450. computeBoundingBox() {
  6451. if (this.boundingBox === null) {
  6452. this.boundingBox = new Box3()
  6453. }
  6454. const position = this.attributes.position
  6455. const morphAttributesPosition = this.morphAttributes.position
  6456. if (position && position.isGLBufferAttribute) {
  6457. console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this)
  6458. this.boundingBox.set(new Vector3(-Infinity, -Infinity, -Infinity), new Vector3(+Infinity, +Infinity, +Infinity))
  6459. return
  6460. }
  6461. if (position !== undefined) {
  6462. this.boundingBox.setFromBufferAttribute(position)
  6463. // process morph attributes if present
  6464. if (morphAttributesPosition) {
  6465. for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
  6466. const morphAttribute = morphAttributesPosition[i]
  6467. _box$1.setFromBufferAttribute(morphAttribute)
  6468. if (this.morphTargetsRelative) {
  6469. _vector$8.addVectors(this.boundingBox.min, _box$1.min)
  6470. this.boundingBox.expandByPoint(_vector$8)
  6471. _vector$8.addVectors(this.boundingBox.max, _box$1.max)
  6472. this.boundingBox.expandByPoint(_vector$8)
  6473. } else {
  6474. this.boundingBox.expandByPoint(_box$1.min)
  6475. this.boundingBox.expandByPoint(_box$1.max)
  6476. }
  6477. }
  6478. }
  6479. } else {
  6480. this.boundingBox.makeEmpty()
  6481. }
  6482. if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
  6483. console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this)
  6484. }
  6485. }
  6486. computeBoundingSphere() {
  6487. if (this.boundingSphere === null) {
  6488. this.boundingSphere = new Sphere()
  6489. }
  6490. const position = this.attributes.position
  6491. const morphAttributesPosition = this.morphAttributes.position
  6492. if (position && position.isGLBufferAttribute) {
  6493. console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this)
  6494. this.boundingSphere.set(new Vector3(), Infinity)
  6495. return
  6496. }
  6497. if (position) {
  6498. // first, find the center of the bounding sphere
  6499. const center = this.boundingSphere.center
  6500. _box$1.setFromBufferAttribute(position)
  6501. // process morph attributes if present
  6502. if (morphAttributesPosition) {
  6503. for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
  6504. const morphAttribute = morphAttributesPosition[i]
  6505. _boxMorphTargets.setFromBufferAttribute(morphAttribute)
  6506. if (this.morphTargetsRelative) {
  6507. _vector$8.addVectors(_box$1.min, _boxMorphTargets.min)
  6508. _box$1.expandByPoint(_vector$8)
  6509. _vector$8.addVectors(_box$1.max, _boxMorphTargets.max)
  6510. _box$1.expandByPoint(_vector$8)
  6511. } else {
  6512. _box$1.expandByPoint(_boxMorphTargets.min)
  6513. _box$1.expandByPoint(_boxMorphTargets.max)
  6514. }
  6515. }
  6516. }
  6517. _box$1.getCenter(center)
  6518. // second, try to find a boundingSphere with a radius smaller than the
  6519. // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
  6520. let maxRadiusSq = 0
  6521. for (let i = 0, il = position.count; i < il; i++) {
  6522. _vector$8.fromBufferAttribute(position, i)
  6523. maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8))
  6524. }
  6525. // process morph attributes if present
  6526. if (morphAttributesPosition) {
  6527. for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
  6528. const morphAttribute = morphAttributesPosition[i]
  6529. const morphTargetsRelative = this.morphTargetsRelative
  6530. for (let j = 0, jl = morphAttribute.count; j < jl; j++) {
  6531. _vector$8.fromBufferAttribute(morphAttribute, j)
  6532. if (morphTargetsRelative) {
  6533. _offset.fromBufferAttribute(position, j)
  6534. _vector$8.add(_offset)
  6535. }
  6536. maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8))
  6537. }
  6538. }
  6539. }
  6540. this.boundingSphere.radius = Math.sqrt(maxRadiusSq)
  6541. if (isNaN(this.boundingSphere.radius)) {
  6542. console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this)
  6543. }
  6544. }
  6545. }
  6546. computeTangents() {
  6547. const index = this.index
  6548. const attributes = this.attributes
  6549. // based on http://www.terathon.com/code/tangent.html
  6550. // (per vertex tangents)
  6551. if (index === null || attributes.position === undefined || attributes.normal === undefined || attributes.uv === undefined) {
  6552. console.error('THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)')
  6553. return
  6554. }
  6555. const indices = index.array
  6556. const positions = attributes.position.array
  6557. const normals = attributes.normal.array
  6558. const uvs = attributes.uv.array
  6559. const nVertices = positions.length / 3
  6560. if (this.hasAttribute('tangent') === false) {
  6561. this.setAttribute('tangent', new BufferAttribute(new Float32Array(4 * nVertices), 4))
  6562. }
  6563. const tangents = this.getAttribute('tangent').array
  6564. const tan1 = [],
  6565. tan2 = []
  6566. for (let i = 0; i < nVertices; i++) {
  6567. tan1[i] = new Vector3()
  6568. tan2[i] = new Vector3()
  6569. }
  6570. const vA = new Vector3(),
  6571. vB = new Vector3(),
  6572. vC = new Vector3(),
  6573. uvA = new Vector2(),
  6574. uvB = new Vector2(),
  6575. uvC = new Vector2(),
  6576. sdir = new Vector3(),
  6577. tdir = new Vector3()
  6578. function handleTriangle(a, b, c) {
  6579. vA.fromArray(positions, a * 3)
  6580. vB.fromArray(positions, b * 3)
  6581. vC.fromArray(positions, c * 3)
  6582. uvA.fromArray(uvs, a * 2)
  6583. uvB.fromArray(uvs, b * 2)
  6584. uvC.fromArray(uvs, c * 2)
  6585. vB.sub(vA)
  6586. vC.sub(vA)
  6587. uvB.sub(uvA)
  6588. uvC.sub(uvA)
  6589. const r = 1.0 / (uvB.x * uvC.y - uvC.x * uvB.y)
  6590. // silently ignore degenerate uv triangles having coincident or colinear vertices
  6591. if (!isFinite(r)) return
  6592. sdir.copy(vB)
  6593. .multiplyScalar(uvC.y)
  6594. .addScaledVector(vC, -uvB.y)
  6595. .multiplyScalar(r)
  6596. tdir.copy(vC)
  6597. .multiplyScalar(uvB.x)
  6598. .addScaledVector(vB, -uvC.x)
  6599. .multiplyScalar(r)
  6600. tan1[a].add(sdir)
  6601. tan1[b].add(sdir)
  6602. tan1[c].add(sdir)
  6603. tan2[a].add(tdir)
  6604. tan2[b].add(tdir)
  6605. tan2[c].add(tdir)
  6606. }
  6607. let groups = this.groups
  6608. if (groups.length === 0) {
  6609. groups = [
  6610. {
  6611. start: 0,
  6612. count: indices.length
  6613. }
  6614. ]
  6615. }
  6616. for (let i = 0, il = groups.length; i < il; ++i) {
  6617. const group = groups[i]
  6618. const start = group.start
  6619. const count = group.count
  6620. for (let j = start, jl = start + count; j < jl; j += 3) {
  6621. handleTriangle(indices[j + 0], indices[j + 1], indices[j + 2])
  6622. }
  6623. }
  6624. const tmp = new Vector3(),
  6625. tmp2 = new Vector3()
  6626. const n = new Vector3(),
  6627. n2 = new Vector3()
  6628. function handleVertex(v) {
  6629. n.fromArray(normals, v * 3)
  6630. n2.copy(n)
  6631. const t = tan1[v]
  6632. // Gram-Schmidt orthogonalize
  6633. tmp.copy(t)
  6634. tmp.sub(n.multiplyScalar(n.dot(t))).normalize()
  6635. // Calculate handedness
  6636. tmp2.crossVectors(n2, t)
  6637. const test = tmp2.dot(tan2[v])
  6638. const w = test < 0.0 ? -1.0 : 1.0
  6639. tangents[v * 4] = tmp.x
  6640. tangents[v * 4 + 1] = tmp.y
  6641. tangents[v * 4 + 2] = tmp.z
  6642. tangents[v * 4 + 3] = w
  6643. }
  6644. for (let i = 0, il = groups.length; i < il; ++i) {
  6645. const group = groups[i]
  6646. const start = group.start
  6647. const count = group.count
  6648. for (let j = start, jl = start + count; j < jl; j += 3) {
  6649. handleVertex(indices[j + 0])
  6650. handleVertex(indices[j + 1])
  6651. handleVertex(indices[j + 2])
  6652. }
  6653. }
  6654. }
  6655. computeVertexNormals() {
  6656. const index = this.index
  6657. const positionAttribute = this.getAttribute('position')
  6658. if (positionAttribute !== undefined) {
  6659. let normalAttribute = this.getAttribute('normal')
  6660. if (normalAttribute === undefined) {
  6661. normalAttribute = new BufferAttribute(new Float32Array(positionAttribute.count * 3), 3)
  6662. this.setAttribute('normal', normalAttribute)
  6663. } else {
  6664. // reset existing normals to zero
  6665. for (let i = 0, il = normalAttribute.count; i < il; i++) {
  6666. normalAttribute.setXYZ(i, 0, 0, 0)
  6667. }
  6668. }
  6669. const pA = new Vector3(),
  6670. pB = new Vector3(),
  6671. pC = new Vector3()
  6672. const nA = new Vector3(),
  6673. nB = new Vector3(),
  6674. nC = new Vector3()
  6675. const cb = new Vector3(),
  6676. ab = new Vector3()
  6677. // indexed elements
  6678. if (index) {
  6679. for (let i = 0, il = index.count; i < il; i += 3) {
  6680. const vA = index.getX(i + 0)
  6681. const vB = index.getX(i + 1)
  6682. const vC = index.getX(i + 2)
  6683. pA.fromBufferAttribute(positionAttribute, vA)
  6684. pB.fromBufferAttribute(positionAttribute, vB)
  6685. pC.fromBufferAttribute(positionAttribute, vC)
  6686. cb.subVectors(pC, pB)
  6687. ab.subVectors(pA, pB)
  6688. cb.cross(ab)
  6689. nA.fromBufferAttribute(normalAttribute, vA)
  6690. nB.fromBufferAttribute(normalAttribute, vB)
  6691. nC.fromBufferAttribute(normalAttribute, vC)
  6692. nA.add(cb)
  6693. nB.add(cb)
  6694. nC.add(cb)
  6695. normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z)
  6696. normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z)
  6697. normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z)
  6698. }
  6699. } else {
  6700. // non-indexed elements (unconnected triangle soup)
  6701. for (let i = 0, il = positionAttribute.count; i < il; i += 3) {
  6702. pA.fromBufferAttribute(positionAttribute, i + 0)
  6703. pB.fromBufferAttribute(positionAttribute, i + 1)
  6704. pC.fromBufferAttribute(positionAttribute, i + 2)
  6705. cb.subVectors(pC, pB)
  6706. ab.subVectors(pA, pB)
  6707. cb.cross(ab)
  6708. normalAttribute.setXYZ(i + 0, cb.x, cb.y, cb.z)
  6709. normalAttribute.setXYZ(i + 1, cb.x, cb.y, cb.z)
  6710. normalAttribute.setXYZ(i + 2, cb.x, cb.y, cb.z)
  6711. }
  6712. }
  6713. this.normalizeNormals()
  6714. normalAttribute.needsUpdate = true
  6715. }
  6716. }
  6717. merge(geometry, offset) {
  6718. if (!(geometry && geometry.isBufferGeometry)) {
  6719. console.error('THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry)
  6720. return
  6721. }
  6722. if (offset === undefined) {
  6723. offset = 0
  6724. console.warn('THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. ' + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.')
  6725. }
  6726. const attributes = this.attributes
  6727. for (const key in attributes) {
  6728. if (geometry.attributes[key] === undefined) continue
  6729. const attribute1 = attributes[key]
  6730. const attributeArray1 = attribute1.array
  6731. const attribute2 = geometry.attributes[key]
  6732. const attributeArray2 = attribute2.array
  6733. const attributeOffset = attribute2.itemSize * offset
  6734. const length = Math.min(attributeArray2.length, attributeArray1.length - attributeOffset)
  6735. for (let i = 0, j = attributeOffset; i < length; i++, j++) {
  6736. attributeArray1[j] = attributeArray2[i]
  6737. }
  6738. }
  6739. return this
  6740. }
  6741. normalizeNormals() {
  6742. const normals = this.attributes.normal
  6743. for (let i = 0, il = normals.count; i < il; i++) {
  6744. _vector$8.fromBufferAttribute(normals, i)
  6745. _vector$8.normalize()
  6746. normals.setXYZ(i, _vector$8.x, _vector$8.y, _vector$8.z)
  6747. }
  6748. }
  6749. toNonIndexed() {
  6750. function convertBufferAttribute(attribute, indices) {
  6751. const array = attribute.array
  6752. const itemSize = attribute.itemSize
  6753. const normalized = attribute.normalized
  6754. const array2 = new array.constructor(indices.length * itemSize)
  6755. let index = 0,
  6756. index2 = 0
  6757. for (let i = 0, l = indices.length; i < l; i++) {
  6758. if (attribute.isInterleavedBufferAttribute) {
  6759. index = indices[i] * attribute.data.stride + attribute.offset
  6760. } else {
  6761. index = indices[i] * itemSize
  6762. }
  6763. for (let j = 0; j < itemSize; j++) {
  6764. array2[index2++] = array[index++]
  6765. }
  6766. }
  6767. return new BufferAttribute(array2, itemSize, normalized)
  6768. }
  6769. //
  6770. if (this.index === null) {
  6771. console.warn('THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.')
  6772. return this
  6773. }
  6774. const geometry2 = new BufferGeometry()
  6775. const indices = this.index.array
  6776. const attributes = this.attributes
  6777. // attributes
  6778. for (const name in attributes) {
  6779. const attribute = attributes[name]
  6780. const newAttribute = convertBufferAttribute(attribute, indices)
  6781. geometry2.setAttribute(name, newAttribute)
  6782. }
  6783. // morph attributes
  6784. const morphAttributes = this.morphAttributes
  6785. for (const name in morphAttributes) {
  6786. const morphArray = []
  6787. const morphAttribute = morphAttributes[name] // morphAttribute: array of Float32BufferAttributes
  6788. for (let i = 0, il = morphAttribute.length; i < il; i++) {
  6789. const attribute = morphAttribute[i]
  6790. const newAttribute = convertBufferAttribute(attribute, indices)
  6791. morphArray.push(newAttribute)
  6792. }
  6793. geometry2.morphAttributes[name] = morphArray
  6794. }
  6795. geometry2.morphTargetsRelative = this.morphTargetsRelative
  6796. // groups
  6797. const groups = this.groups
  6798. for (let i = 0, l = groups.length; i < l; i++) {
  6799. const group = groups[i]
  6800. geometry2.addGroup(group.start, group.count, group.materialIndex)
  6801. }
  6802. return geometry2
  6803. }
  6804. toJSON() {
  6805. const data = {
  6806. metadata: {
  6807. version: 4.5,
  6808. type: 'BufferGeometry',
  6809. generator: 'BufferGeometry.toJSON'
  6810. }
  6811. }
  6812. // standard BufferGeometry serialization
  6813. data.uuid = this.uuid
  6814. data.type = this.type
  6815. if (this.name !== '') data.name = this.name
  6816. if (Object.keys(this.userData).length > 0) data.userData = this.userData
  6817. if (this.parameters !== undefined) {
  6818. const parameters = this.parameters
  6819. for (const key in parameters) {
  6820. if (parameters[key] !== undefined) data[key] = parameters[key]
  6821. }
  6822. return data
  6823. }
  6824. // for simplicity the code assumes attributes are not shared across geometries, see #15811
  6825. data.data = { attributes: {} }
  6826. const index = this.index
  6827. if (index !== null) {
  6828. data.data.index = {
  6829. type: index.array.constructor.name,
  6830. array: Array.prototype.slice.call(index.array)
  6831. }
  6832. }
  6833. const attributes = this.attributes
  6834. for (const key in attributes) {
  6835. const attribute = attributes[key]
  6836. data.data.attributes[key] = attribute.toJSON(data.data)
  6837. }
  6838. const morphAttributes = {}
  6839. let hasMorphAttributes = false
  6840. for (const key in this.morphAttributes) {
  6841. const attributeArray = this.morphAttributes[key]
  6842. const array = []
  6843. for (let i = 0, il = attributeArray.length; i < il; i++) {
  6844. const attribute = attributeArray[i]
  6845. array.push(attribute.toJSON(data.data))
  6846. }
  6847. if (array.length > 0) {
  6848. morphAttributes[key] = array
  6849. hasMorphAttributes = true
  6850. }
  6851. }
  6852. if (hasMorphAttributes) {
  6853. data.data.morphAttributes = morphAttributes
  6854. data.data.morphTargetsRelative = this.morphTargetsRelative
  6855. }
  6856. const groups = this.groups
  6857. if (groups.length > 0) {
  6858. data.data.groups = JSON.parse(JSON.stringify(groups))
  6859. }
  6860. const boundingSphere = this.boundingSphere
  6861. if (boundingSphere !== null) {
  6862. data.data.boundingSphere = {
  6863. center: boundingSphere.center.toArray(),
  6864. radius: boundingSphere.radius
  6865. }
  6866. }
  6867. return data
  6868. }
  6869. clone() {
  6870. return new this.constructor().copy(this)
  6871. }
  6872. copy(source) {
  6873. // reset
  6874. this.index = null
  6875. this.attributes = {}
  6876. this.morphAttributes = {}
  6877. this.groups = []
  6878. this.boundingBox = null
  6879. this.boundingSphere = null
  6880. // used for storing cloned, shared data
  6881. const data = {}
  6882. // name
  6883. this.name = source.name
  6884. // index
  6885. const index = source.index
  6886. if (index !== null) {
  6887. this.setIndex(index.clone(data))
  6888. }
  6889. // attributes
  6890. const attributes = source.attributes
  6891. for (const name in attributes) {
  6892. const attribute = attributes[name]
  6893. this.setAttribute(name, attribute.clone(data))
  6894. }
  6895. // morph attributes
  6896. const morphAttributes = source.morphAttributes
  6897. for (const name in morphAttributes) {
  6898. const array = []
  6899. const morphAttribute = morphAttributes[name] // morphAttribute: array of Float32BufferAttributes
  6900. for (let i = 0, l = morphAttribute.length; i < l; i++) {
  6901. array.push(morphAttribute[i].clone(data))
  6902. }
  6903. this.morphAttributes[name] = array
  6904. }
  6905. this.morphTargetsRelative = source.morphTargetsRelative
  6906. // groups
  6907. const groups = source.groups
  6908. for (let i = 0, l = groups.length; i < l; i++) {
  6909. const group = groups[i]
  6910. this.addGroup(group.start, group.count, group.materialIndex)
  6911. }
  6912. // bounding box
  6913. const boundingBox = source.boundingBox
  6914. if (boundingBox !== null) {
  6915. this.boundingBox = boundingBox.clone()
  6916. }
  6917. // bounding sphere
  6918. const boundingSphere = source.boundingSphere
  6919. if (boundingSphere !== null) {
  6920. this.boundingSphere = boundingSphere.clone()
  6921. }
  6922. // draw range
  6923. this.drawRange.start = source.drawRange.start
  6924. this.drawRange.count = source.drawRange.count
  6925. // user data
  6926. this.userData = source.userData
  6927. // geometry generator parameters
  6928. if (source.parameters !== undefined) this.parameters = Object.assign({}, source.parameters)
  6929. return this
  6930. }
  6931. dispose() {
  6932. this.dispatchEvent({ type: 'dispose' })
  6933. }
  6934. }
  6935. const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4()
  6936. const _ray$2 = /*@__PURE__*/ new Ray()
  6937. const _sphere$3 = /*@__PURE__*/ new Sphere()
  6938. const _vA$1 = /*@__PURE__*/ new Vector3()
  6939. const _vB$1 = /*@__PURE__*/ new Vector3()
  6940. const _vC$1 = /*@__PURE__*/ new Vector3()
  6941. const _tempA = /*@__PURE__*/ new Vector3()
  6942. const _tempB = /*@__PURE__*/ new Vector3()
  6943. const _tempC = /*@__PURE__*/ new Vector3()
  6944. const _morphA = /*@__PURE__*/ new Vector3()
  6945. const _morphB = /*@__PURE__*/ new Vector3()
  6946. const _morphC = /*@__PURE__*/ new Vector3()
  6947. const _uvA$1 = /*@__PURE__*/ new Vector2()
  6948. const _uvB$1 = /*@__PURE__*/ new Vector2()
  6949. const _uvC$1 = /*@__PURE__*/ new Vector2()
  6950. const _intersectionPoint = /*@__PURE__*/ new Vector3()
  6951. const _intersectionPointWorld = /*@__PURE__*/ new Vector3()
  6952. class Mesh extends Object3D {
  6953. constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) {
  6954. super()
  6955. this.isMesh = true
  6956. this.type = 'Mesh'
  6957. this.geometry = geometry
  6958. this.material = material
  6959. this.updateMorphTargets()
  6960. }
  6961. copy(source, recursive) {
  6962. super.copy(source, recursive)
  6963. if (source.morphTargetInfluences !== undefined) {
  6964. this.morphTargetInfluences = source.morphTargetInfluences.slice()
  6965. }
  6966. if (source.morphTargetDictionary !== undefined) {
  6967. this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary)
  6968. }
  6969. this.material = source.material
  6970. this.geometry = source.geometry
  6971. return this
  6972. }
  6973. updateMorphTargets() {
  6974. const geometry = this.geometry
  6975. const morphAttributes = geometry.morphAttributes
  6976. const keys = Object.keys(morphAttributes)
  6977. if (keys.length > 0) {
  6978. const morphAttribute = morphAttributes[keys[0]]
  6979. if (morphAttribute !== undefined) {
  6980. this.morphTargetInfluences = []
  6981. this.morphTargetDictionary = {}
  6982. for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
  6983. const name = morphAttribute[m].name || String(m)
  6984. this.morphTargetInfluences.push(0)
  6985. this.morphTargetDictionary[name] = m
  6986. }
  6987. }
  6988. }
  6989. }
  6990. raycast(raycaster, intersects) {
  6991. const geometry = this.geometry
  6992. const material = this.material
  6993. const matrixWorld = this.matrixWorld
  6994. if (material === undefined) return
  6995. // Checking boundingSphere distance to ray
  6996. if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
  6997. _sphere$3.copy(geometry.boundingSphere)
  6998. _sphere$3.applyMatrix4(matrixWorld)
  6999. if (raycaster.ray.intersectsSphere(_sphere$3) === false) return
  7000. //
  7001. _inverseMatrix$2.copy(matrixWorld).invert()
  7002. _ray$2.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2)
  7003. // Check boundingBox before continuing
  7004. if (geometry.boundingBox !== null) {
  7005. if (_ray$2.intersectsBox(geometry.boundingBox) === false) return
  7006. }
  7007. let intersection
  7008. const index = geometry.index
  7009. const position = geometry.attributes.position
  7010. const morphPosition = geometry.morphAttributes.position
  7011. const morphTargetsRelative = geometry.morphTargetsRelative
  7012. const uv = geometry.attributes.uv
  7013. const uv2 = geometry.attributes.uv2
  7014. const groups = geometry.groups
  7015. const drawRange = geometry.drawRange
  7016. if (index !== null) {
  7017. // indexed buffer geometry
  7018. if (Array.isArray(material)) {
  7019. for (let i = 0, il = groups.length; i < il; i++) {
  7020. const group = groups[i]
  7021. const groupMaterial = material[group.materialIndex]
  7022. const start = Math.max(group.start, drawRange.start)
  7023. const end = Math.min(index.count, Math.min(group.start + group.count, drawRange.start + drawRange.count))
  7024. for (let j = start, jl = end; j < jl; j += 3) {
  7025. const a = index.getX(j)
  7026. const b = index.getX(j + 1)
  7027. const c = index.getX(j + 2)
  7028. intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c)
  7029. if (intersection) {
  7030. intersection.faceIndex = Math.floor(j / 3) // triangle number in indexed buffer semantics
  7031. intersection.face.materialIndex = group.materialIndex
  7032. intersects.push(intersection)
  7033. }
  7034. }
  7035. }
  7036. } else {
  7037. const start = Math.max(0, drawRange.start)
  7038. const end = Math.min(index.count, drawRange.start + drawRange.count)
  7039. for (let i = start, il = end; i < il; i += 3) {
  7040. const a = index.getX(i)
  7041. const b = index.getX(i + 1)
  7042. const c = index.getX(i + 2)
  7043. intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c)
  7044. if (intersection) {
  7045. intersection.faceIndex = Math.floor(i / 3) // triangle number in indexed buffer semantics
  7046. intersects.push(intersection)
  7047. }
  7048. }
  7049. }
  7050. } else if (position !== undefined) {
  7051. // non-indexed buffer geometry
  7052. if (Array.isArray(material)) {
  7053. for (let i = 0, il = groups.length; i < il; i++) {
  7054. const group = groups[i]
  7055. const groupMaterial = material[group.materialIndex]
  7056. const start = Math.max(group.start, drawRange.start)
  7057. const end = Math.min(position.count, Math.min(group.start + group.count, drawRange.start + drawRange.count))
  7058. for (let j = start, jl = end; j < jl; j += 3) {
  7059. const a = j
  7060. const b = j + 1
  7061. const c = j + 2
  7062. intersection = checkBufferGeometryIntersection(this, groupMaterial, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c)
  7063. if (intersection) {
  7064. intersection.faceIndex = Math.floor(j / 3) // triangle number in non-indexed buffer semantics
  7065. intersection.face.materialIndex = group.materialIndex
  7066. intersects.push(intersection)
  7067. }
  7068. }
  7069. }
  7070. } else {
  7071. const start = Math.max(0, drawRange.start)
  7072. const end = Math.min(position.count, drawRange.start + drawRange.count)
  7073. for (let i = start, il = end; i < il; i += 3) {
  7074. const a = i
  7075. const b = i + 1
  7076. const c = i + 2
  7077. intersection = checkBufferGeometryIntersection(this, material, raycaster, _ray$2, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c)
  7078. if (intersection) {
  7079. intersection.faceIndex = Math.floor(i / 3) // triangle number in non-indexed buffer semantics
  7080. intersects.push(intersection)
  7081. }
  7082. }
  7083. }
  7084. }
  7085. }
  7086. }
  7087. function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
  7088. let intersect
  7089. if (material.side === BackSide) {
  7090. intersect = ray.intersectTriangle(pC, pB, pA, true, point)
  7091. } else {
  7092. intersect = ray.intersectTriangle(pA, pB, pC, material.side !== DoubleSide, point)
  7093. }
  7094. if (intersect === null) return null
  7095. _intersectionPointWorld.copy(point)
  7096. _intersectionPointWorld.applyMatrix4(object.matrixWorld)
  7097. const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld)
  7098. if (distance < raycaster.near || distance > raycaster.far) return null
  7099. return {
  7100. distance: distance,
  7101. point: _intersectionPointWorld.clone(),
  7102. object: object
  7103. }
  7104. }
  7105. function checkBufferGeometryIntersection(object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c) {
  7106. _vA$1.fromBufferAttribute(position, a)
  7107. _vB$1.fromBufferAttribute(position, b)
  7108. _vC$1.fromBufferAttribute(position, c)
  7109. const morphInfluences = object.morphTargetInfluences
  7110. if (morphPosition && morphInfluences) {
  7111. _morphA.set(0, 0, 0)
  7112. _morphB.set(0, 0, 0)
  7113. _morphC.set(0, 0, 0)
  7114. for (let i = 0, il = morphPosition.length; i < il; i++) {
  7115. const influence = morphInfluences[i]
  7116. const morphAttribute = morphPosition[i]
  7117. if (influence === 0) continue
  7118. _tempA.fromBufferAttribute(morphAttribute, a)
  7119. _tempB.fromBufferAttribute(morphAttribute, b)
  7120. _tempC.fromBufferAttribute(morphAttribute, c)
  7121. if (morphTargetsRelative) {
  7122. _morphA.addScaledVector(_tempA, influence)
  7123. _morphB.addScaledVector(_tempB, influence)
  7124. _morphC.addScaledVector(_tempC, influence)
  7125. } else {
  7126. _morphA.addScaledVector(_tempA.sub(_vA$1), influence)
  7127. _morphB.addScaledVector(_tempB.sub(_vB$1), influence)
  7128. _morphC.addScaledVector(_tempC.sub(_vC$1), influence)
  7129. }
  7130. }
  7131. _vA$1.add(_morphA)
  7132. _vB$1.add(_morphB)
  7133. _vC$1.add(_morphC)
  7134. }
  7135. if (object.isSkinnedMesh) {
  7136. object.boneTransform(a, _vA$1)
  7137. object.boneTransform(b, _vB$1)
  7138. object.boneTransform(c, _vC$1)
  7139. }
  7140. const intersection = checkIntersection(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint)
  7141. if (intersection) {
  7142. if (uv) {
  7143. _uvA$1.fromBufferAttribute(uv, a)
  7144. _uvB$1.fromBufferAttribute(uv, b)
  7145. _uvC$1.fromBufferAttribute(uv, c)
  7146. intersection.uv = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2())
  7147. }
  7148. if (uv2) {
  7149. _uvA$1.fromBufferAttribute(uv2, a)
  7150. _uvB$1.fromBufferAttribute(uv2, b)
  7151. _uvC$1.fromBufferAttribute(uv2, c)
  7152. intersection.uv2 = Triangle.getUV(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2())
  7153. }
  7154. const face = {
  7155. a: a,
  7156. b: b,
  7157. c: c,
  7158. normal: new Vector3(),
  7159. materialIndex: 0
  7160. }
  7161. Triangle.getNormal(_vA$1, _vB$1, _vC$1, face.normal)
  7162. intersection.face = face
  7163. }
  7164. return intersection
  7165. }
  7166. class BoxGeometry extends BufferGeometry {
  7167. constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
  7168. super()
  7169. this.type = 'BoxGeometry'
  7170. this.parameters = {
  7171. width: width,
  7172. height: height,
  7173. depth: depth,
  7174. widthSegments: widthSegments,
  7175. heightSegments: heightSegments,
  7176. depthSegments: depthSegments
  7177. }
  7178. const scope = this
  7179. // segments
  7180. widthSegments = Math.floor(widthSegments)
  7181. heightSegments = Math.floor(heightSegments)
  7182. depthSegments = Math.floor(depthSegments)
  7183. // buffers
  7184. const indices = []
  7185. const vertices = []
  7186. const normals = []
  7187. const uvs = []
  7188. // helper variables
  7189. let numberOfVertices = 0
  7190. let groupStart = 0
  7191. // build each side of the box geometry
  7192. buildPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0) // px
  7193. buildPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1) // nx
  7194. buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2) // py
  7195. buildPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3) // ny
  7196. buildPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4) // pz
  7197. buildPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5) // nz
  7198. // build geometry
  7199. this.setIndex(indices)
  7200. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  7201. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  7202. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  7203. function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) {
  7204. const segmentWidth = width / gridX
  7205. const segmentHeight = height / gridY
  7206. const widthHalf = width / 2
  7207. const heightHalf = height / 2
  7208. const depthHalf = depth / 2
  7209. const gridX1 = gridX + 1
  7210. const gridY1 = gridY + 1
  7211. let vertexCounter = 0
  7212. let groupCount = 0
  7213. const vector = new Vector3()
  7214. // generate vertices, normals and uvs
  7215. for (let iy = 0; iy < gridY1; iy++) {
  7216. const y = iy * segmentHeight - heightHalf
  7217. for (let ix = 0; ix < gridX1; ix++) {
  7218. const x = ix * segmentWidth - widthHalf
  7219. // set values to correct vector component
  7220. vector[u] = x * udir
  7221. vector[v] = y * vdir
  7222. vector[w] = depthHalf
  7223. // now apply vector to vertex buffer
  7224. vertices.push(vector.x, vector.y, vector.z)
  7225. // set values to correct vector component
  7226. vector[u] = 0
  7227. vector[v] = 0
  7228. vector[w] = depth > 0 ? 1 : -1
  7229. // now apply vector to normal buffer
  7230. normals.push(vector.x, vector.y, vector.z)
  7231. // uvs
  7232. uvs.push(ix / gridX)
  7233. uvs.push(1 - iy / gridY)
  7234. // counters
  7235. vertexCounter += 1
  7236. }
  7237. }
  7238. // indices
  7239. // 1. you need three indices to draw a single face
  7240. // 2. a single segment consists of two faces
  7241. // 3. so we need to generate six (2*3) indices per segment
  7242. for (let iy = 0; iy < gridY; iy++) {
  7243. for (let ix = 0; ix < gridX; ix++) {
  7244. const a = numberOfVertices + ix + gridX1 * iy
  7245. const b = numberOfVertices + ix + gridX1 * (iy + 1)
  7246. const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1)
  7247. const d = numberOfVertices + (ix + 1) + gridX1 * iy
  7248. // faces
  7249. indices.push(a, b, d)
  7250. indices.push(b, c, d)
  7251. // increase counter
  7252. groupCount += 6
  7253. }
  7254. }
  7255. // add a group to the geometry. this will ensure multi material support
  7256. scope.addGroup(groupStart, groupCount, materialIndex)
  7257. // calculate new start value for groups
  7258. groupStart += groupCount
  7259. // update total number of vertices
  7260. numberOfVertices += vertexCounter
  7261. }
  7262. }
  7263. static fromJSON(data) {
  7264. return new BoxGeometry(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments)
  7265. }
  7266. }
  7267. /**
  7268. * Uniform Utilities
  7269. */
  7270. function cloneUniforms(src) {
  7271. const dst = {}
  7272. for (const u in src) {
  7273. dst[u] = {}
  7274. for (const p in src[u]) {
  7275. const property = src[u][p]
  7276. if (
  7277. property &&
  7278. (property.isColor || property.isMatrix3 || property.isMatrix4 || property.isVector2 || property.isVector3 || property.isVector4 || property.isTexture || property.isQuaternion)
  7279. ) {
  7280. dst[u][p] = property.clone()
  7281. } else if (Array.isArray(property)) {
  7282. dst[u][p] = property.slice()
  7283. } else {
  7284. dst[u][p] = property
  7285. }
  7286. }
  7287. }
  7288. return dst
  7289. }
  7290. function mergeUniforms(uniforms) {
  7291. const merged = {}
  7292. for (let u = 0; u < uniforms.length; u++) {
  7293. const tmp = cloneUniforms(uniforms[u])
  7294. for (const p in tmp) {
  7295. merged[p] = tmp[p]
  7296. }
  7297. }
  7298. return merged
  7299. }
  7300. // Legacy
  7301. const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }
  7302. var default_vertex = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'
  7303. var default_fragment = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'
  7304. class ShaderMaterial extends Material {
  7305. constructor(parameters) {
  7306. super()
  7307. this.isShaderMaterial = true
  7308. this.type = 'ShaderMaterial'
  7309. this.defines = {}
  7310. this.uniforms = {}
  7311. this.vertexShader = default_vertex
  7312. this.fragmentShader = default_fragment
  7313. this.linewidth = 1
  7314. this.wireframe = false
  7315. this.wireframeLinewidth = 1
  7316. this.fog = false // set to use scene fog
  7317. this.lights = false // set to use scene lights
  7318. this.clipping = false // set to use user-defined clipping planes
  7319. this.extensions = {
  7320. derivatives: false, // set to use derivatives
  7321. fragDepth: false, // set to use fragment depth values
  7322. drawBuffers: false, // set to use draw buffers
  7323. shaderTextureLOD: false // set to use shader texture LOD
  7324. }
  7325. // When rendered geometry doesn't include these attributes but the material does,
  7326. // use these default values in WebGL. This avoids errors when buffer data is missing.
  7327. this.defaultAttributeValues = {
  7328. color: [1, 1, 1],
  7329. uv: [0, 0],
  7330. uv2: [0, 0]
  7331. }
  7332. this.index0AttributeName = undefined
  7333. this.uniformsNeedUpdate = false
  7334. this.glslVersion = null
  7335. if (parameters !== undefined) {
  7336. if (parameters.attributes !== undefined) {
  7337. console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.')
  7338. }
  7339. this.setValues(parameters)
  7340. }
  7341. }
  7342. copy(source) {
  7343. super.copy(source)
  7344. this.fragmentShader = source.fragmentShader
  7345. this.vertexShader = source.vertexShader
  7346. this.uniforms = cloneUniforms(source.uniforms)
  7347. this.defines = Object.assign({}, source.defines)
  7348. this.wireframe = source.wireframe
  7349. this.wireframeLinewidth = source.wireframeLinewidth
  7350. this.fog = source.fog
  7351. this.lights = source.lights
  7352. this.clipping = source.clipping
  7353. this.extensions = Object.assign({}, source.extensions)
  7354. this.glslVersion = source.glslVersion
  7355. return this
  7356. }
  7357. toJSON(meta) {
  7358. const data = super.toJSON(meta)
  7359. data.glslVersion = this.glslVersion
  7360. data.uniforms = {}
  7361. for (const name in this.uniforms) {
  7362. const uniform = this.uniforms[name]
  7363. const value = uniform.value
  7364. if (value && value.isTexture) {
  7365. data.uniforms[name] = {
  7366. type: 't',
  7367. value: value.toJSON(meta).uuid
  7368. }
  7369. } else if (value && value.isColor) {
  7370. data.uniforms[name] = {
  7371. type: 'c',
  7372. value: value.getHex()
  7373. }
  7374. } else if (value && value.isVector2) {
  7375. data.uniforms[name] = {
  7376. type: 'v2',
  7377. value: value.toArray()
  7378. }
  7379. } else if (value && value.isVector3) {
  7380. data.uniforms[name] = {
  7381. type: 'v3',
  7382. value: value.toArray()
  7383. }
  7384. } else if (value && value.isVector4) {
  7385. data.uniforms[name] = {
  7386. type: 'v4',
  7387. value: value.toArray()
  7388. }
  7389. } else if (value && value.isMatrix3) {
  7390. data.uniforms[name] = {
  7391. type: 'm3',
  7392. value: value.toArray()
  7393. }
  7394. } else if (value && value.isMatrix4) {
  7395. data.uniforms[name] = {
  7396. type: 'm4',
  7397. value: value.toArray()
  7398. }
  7399. } else {
  7400. data.uniforms[name] = {
  7401. value: value
  7402. }
  7403. // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
  7404. }
  7405. }
  7406. if (Object.keys(this.defines).length > 0) data.defines = this.defines
  7407. data.vertexShader = this.vertexShader
  7408. data.fragmentShader = this.fragmentShader
  7409. const extensions = {}
  7410. for (const key in this.extensions) {
  7411. if (this.extensions[key] === true) extensions[key] = true
  7412. }
  7413. if (Object.keys(extensions).length > 0) data.extensions = extensions
  7414. return data
  7415. }
  7416. }
  7417. class Camera extends Object3D {
  7418. constructor() {
  7419. super()
  7420. this.isCamera = true
  7421. this.type = 'Camera'
  7422. this.matrixWorldInverse = new Matrix4()
  7423. this.projectionMatrix = new Matrix4()
  7424. this.projectionMatrixInverse = new Matrix4()
  7425. }
  7426. copy(source, recursive) {
  7427. super.copy(source, recursive)
  7428. this.matrixWorldInverse.copy(source.matrixWorldInverse)
  7429. this.projectionMatrix.copy(source.projectionMatrix)
  7430. this.projectionMatrixInverse.copy(source.projectionMatrixInverse)
  7431. return this
  7432. }
  7433. getWorldDirection(target) {
  7434. this.updateWorldMatrix(true, false)
  7435. const e = this.matrixWorld.elements
  7436. return target.set(-e[8], -e[9], -e[10]).normalize()
  7437. }
  7438. updateMatrixWorld(force) {
  7439. super.updateMatrixWorld(force)
  7440. this.matrixWorldInverse.copy(this.matrixWorld).invert()
  7441. }
  7442. updateWorldMatrix(updateParents, updateChildren) {
  7443. super.updateWorldMatrix(updateParents, updateChildren)
  7444. this.matrixWorldInverse.copy(this.matrixWorld).invert()
  7445. }
  7446. clone() {
  7447. return new this.constructor().copy(this)
  7448. }
  7449. }
  7450. class PerspectiveCamera extends Camera {
  7451. constructor(fov = 50, aspect = 1, near = 0.1, far = 2000) {
  7452. super()
  7453. this.isPerspectiveCamera = true
  7454. this.type = 'PerspectiveCamera'
  7455. this.fov = fov
  7456. this.zoom = 1
  7457. this.near = near
  7458. this.far = far
  7459. this.focus = 10
  7460. this.aspect = aspect
  7461. this.view = null
  7462. this.filmGauge = 35 // width of the film (default in millimeters)
  7463. this.filmOffset = 0 // horizontal film offset (same unit as gauge)
  7464. this.updateProjectionMatrix()
  7465. }
  7466. copy(source, recursive) {
  7467. super.copy(source, recursive)
  7468. this.fov = source.fov
  7469. this.zoom = source.zoom
  7470. this.near = source.near
  7471. this.far = source.far
  7472. this.focus = source.focus
  7473. this.aspect = source.aspect
  7474. this.view = source.view === null ? null : Object.assign({}, source.view)
  7475. this.filmGauge = source.filmGauge
  7476. this.filmOffset = source.filmOffset
  7477. return this
  7478. }
  7479. /**
  7480. * Sets the FOV by focal length in respect to the current .filmGauge.
  7481. *
  7482. * The default film gauge is 35, so that the focal length can be specified for
  7483. * a 35mm (full frame) camera.
  7484. *
  7485. * Values for focal length and film gauge must have the same unit.
  7486. */
  7487. setFocalLength(focalLength) {
  7488. /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
  7489. const vExtentSlope = (0.5 * this.getFilmHeight()) / focalLength
  7490. this.fov = RAD2DEG * 2 * Math.atan(vExtentSlope)
  7491. this.updateProjectionMatrix()
  7492. }
  7493. /**
  7494. * Calculates the focal length from the current .fov and .filmGauge.
  7495. */
  7496. getFocalLength() {
  7497. const vExtentSlope = Math.tan(DEG2RAD * 0.5 * this.fov)
  7498. return (0.5 * this.getFilmHeight()) / vExtentSlope
  7499. }
  7500. getEffectiveFOV() {
  7501. return RAD2DEG * 2 * Math.atan(Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom)
  7502. }
  7503. getFilmWidth() {
  7504. // film not completely covered in portrait format (aspect < 1)
  7505. return this.filmGauge * Math.min(this.aspect, 1)
  7506. }
  7507. getFilmHeight() {
  7508. // film not completely covered in landscape format (aspect > 1)
  7509. return this.filmGauge / Math.max(this.aspect, 1)
  7510. }
  7511. /**
  7512. * Sets an offset in a larger frustum. This is useful for multi-window or
  7513. * multi-monitor/multi-machine setups.
  7514. *
  7515. * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
  7516. * the monitors are in grid like this
  7517. *
  7518. * +---+---+---+
  7519. * | A | B | C |
  7520. * +---+---+---+
  7521. * | D | E | F |
  7522. * +---+---+---+
  7523. *
  7524. * then for each monitor you would call it like this
  7525. *
  7526. * const w = 1920;
  7527. * const h = 1080;
  7528. * const fullWidth = w * 3;
  7529. * const fullHeight = h * 2;
  7530. *
  7531. * --A--
  7532. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
  7533. * --B--
  7534. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
  7535. * --C--
  7536. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
  7537. * --D--
  7538. * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
  7539. * --E--
  7540. * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
  7541. * --F--
  7542. * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
  7543. *
  7544. * Note there is no reason monitors have to be the same size or in a grid.
  7545. */
  7546. setViewOffset(fullWidth, fullHeight, x, y, width, height) {
  7547. this.aspect = fullWidth / fullHeight
  7548. if (this.view === null) {
  7549. this.view = {
  7550. enabled: true,
  7551. fullWidth: 1,
  7552. fullHeight: 1,
  7553. offsetX: 0,
  7554. offsetY: 0,
  7555. width: 1,
  7556. height: 1
  7557. }
  7558. }
  7559. this.view.enabled = true
  7560. this.view.fullWidth = fullWidth
  7561. this.view.fullHeight = fullHeight
  7562. this.view.offsetX = x
  7563. this.view.offsetY = y
  7564. this.view.width = width
  7565. this.view.height = height
  7566. this.updateProjectionMatrix()
  7567. }
  7568. clearViewOffset() {
  7569. if (this.view !== null) {
  7570. this.view.enabled = false
  7571. }
  7572. this.updateProjectionMatrix()
  7573. }
  7574. updateProjectionMatrix() {
  7575. const near = this.near
  7576. let top = (near * Math.tan(DEG2RAD * 0.5 * this.fov)) / this.zoom
  7577. let height = 2 * top
  7578. let width = this.aspect * height
  7579. let left = -0.5 * width
  7580. const view = this.view
  7581. if (this.view !== null && this.view.enabled) {
  7582. const fullWidth = view.fullWidth,
  7583. fullHeight = view.fullHeight
  7584. left += (view.offsetX * width) / fullWidth
  7585. top -= (view.offsetY * height) / fullHeight
  7586. width *= view.width / fullWidth
  7587. height *= view.height / fullHeight
  7588. }
  7589. const skew = this.filmOffset
  7590. if (skew !== 0) left += (near * skew) / this.getFilmWidth()
  7591. this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far)
  7592. this.projectionMatrixInverse.copy(this.projectionMatrix).invert()
  7593. }
  7594. toJSON(meta) {
  7595. const data = super.toJSON(meta)
  7596. data.object.fov = this.fov
  7597. data.object.zoom = this.zoom
  7598. data.object.near = this.near
  7599. data.object.far = this.far
  7600. data.object.focus = this.focus
  7601. data.object.aspect = this.aspect
  7602. if (this.view !== null) data.object.view = Object.assign({}, this.view)
  7603. data.object.filmGauge = this.filmGauge
  7604. data.object.filmOffset = this.filmOffset
  7605. return data
  7606. }
  7607. }
  7608. const fov = 90,
  7609. aspect = 1
  7610. class CubeCamera extends Object3D {
  7611. constructor(near, far, renderTarget) {
  7612. super()
  7613. this.type = 'CubeCamera'
  7614. if (renderTarget.isWebGLCubeRenderTarget !== true) {
  7615. console.error('THREE.CubeCamera: The constructor now expects an instance of WebGLCubeRenderTarget as third parameter.')
  7616. return
  7617. }
  7618. this.renderTarget = renderTarget
  7619. const cameraPX = new PerspectiveCamera(fov, aspect, near, far)
  7620. cameraPX.layers = this.layers
  7621. cameraPX.up.set(0, -1, 0)
  7622. cameraPX.lookAt(new Vector3(1, 0, 0))
  7623. this.add(cameraPX)
  7624. const cameraNX = new PerspectiveCamera(fov, aspect, near, far)
  7625. cameraNX.layers = this.layers
  7626. cameraNX.up.set(0, -1, 0)
  7627. cameraNX.lookAt(new Vector3(-1, 0, 0))
  7628. this.add(cameraNX)
  7629. const cameraPY = new PerspectiveCamera(fov, aspect, near, far)
  7630. cameraPY.layers = this.layers
  7631. cameraPY.up.set(0, 0, 1)
  7632. cameraPY.lookAt(new Vector3(0, 1, 0))
  7633. this.add(cameraPY)
  7634. const cameraNY = new PerspectiveCamera(fov, aspect, near, far)
  7635. cameraNY.layers = this.layers
  7636. cameraNY.up.set(0, 0, -1)
  7637. cameraNY.lookAt(new Vector3(0, -1, 0))
  7638. this.add(cameraNY)
  7639. const cameraPZ = new PerspectiveCamera(fov, aspect, near, far)
  7640. cameraPZ.layers = this.layers
  7641. cameraPZ.up.set(0, -1, 0)
  7642. cameraPZ.lookAt(new Vector3(0, 0, 1))
  7643. this.add(cameraPZ)
  7644. const cameraNZ = new PerspectiveCamera(fov, aspect, near, far)
  7645. cameraNZ.layers = this.layers
  7646. cameraNZ.up.set(0, -1, 0)
  7647. cameraNZ.lookAt(new Vector3(0, 0, -1))
  7648. this.add(cameraNZ)
  7649. }
  7650. update(renderer, scene) {
  7651. if (this.parent === null) this.updateMatrixWorld()
  7652. const renderTarget = this.renderTarget
  7653. const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = this.children
  7654. const currentRenderTarget = renderer.getRenderTarget()
  7655. const currentToneMapping = renderer.toneMapping
  7656. const currentXrEnabled = renderer.xr.enabled
  7657. renderer.toneMapping = NoToneMapping
  7658. renderer.xr.enabled = false
  7659. const generateMipmaps = renderTarget.texture.generateMipmaps
  7660. renderTarget.texture.generateMipmaps = false
  7661. renderer.setRenderTarget(renderTarget, 0)
  7662. renderer.render(scene, cameraPX)
  7663. renderer.setRenderTarget(renderTarget, 1)
  7664. renderer.render(scene, cameraNX)
  7665. renderer.setRenderTarget(renderTarget, 2)
  7666. renderer.render(scene, cameraPY)
  7667. renderer.setRenderTarget(renderTarget, 3)
  7668. renderer.render(scene, cameraNY)
  7669. renderer.setRenderTarget(renderTarget, 4)
  7670. renderer.render(scene, cameraPZ)
  7671. renderTarget.texture.generateMipmaps = generateMipmaps
  7672. renderer.setRenderTarget(renderTarget, 5)
  7673. renderer.render(scene, cameraNZ)
  7674. renderer.setRenderTarget(currentRenderTarget)
  7675. renderer.toneMapping = currentToneMapping
  7676. renderer.xr.enabled = currentXrEnabled
  7677. renderTarget.texture.needsPMREMUpdate = true
  7678. }
  7679. }
  7680. class CubeTexture extends Texture {
  7681. constructor(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
  7682. images = images !== undefined ? images : []
  7683. mapping = mapping !== undefined ? mapping : CubeReflectionMapping
  7684. super(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding)
  7685. this.isCubeTexture = true
  7686. this.flipY = false
  7687. }
  7688. get images() {
  7689. return this.image
  7690. }
  7691. set images(value) {
  7692. this.image = value
  7693. }
  7694. }
  7695. class WebGLCubeRenderTarget extends WebGLRenderTarget {
  7696. constructor(size, options = {}) {
  7697. super(size, size, options)
  7698. this.isWebGLCubeRenderTarget = true
  7699. const image = { width: size, height: size, depth: 1 }
  7700. const images = [image, image, image, image, image, image]
  7701. this.texture = new CubeTexture(images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding)
  7702. // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
  7703. // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
  7704. // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
  7705. // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
  7706. // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
  7707. // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
  7708. this.texture.isRenderTargetTexture = true
  7709. this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false
  7710. this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter
  7711. }
  7712. fromEquirectangularTexture(renderer, texture) {
  7713. this.texture.type = texture.type
  7714. this.texture.encoding = texture.encoding
  7715. this.texture.generateMipmaps = texture.generateMipmaps
  7716. this.texture.minFilter = texture.minFilter
  7717. this.texture.magFilter = texture.magFilter
  7718. const shader = {
  7719. uniforms: {
  7720. tEquirect: { value: null }
  7721. },
  7722. vertexShader: /* glsl */ `
  7723. varying vec3 vWorldDirection;
  7724. vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
  7725. return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
  7726. }
  7727. void main() {
  7728. vWorldDirection = transformDirection( position, modelMatrix );
  7729. #include <begin_vertex>
  7730. #include <project_vertex>
  7731. }
  7732. `,
  7733. fragmentShader: /* glsl */ `
  7734. uniform sampler2D tEquirect;
  7735. varying vec3 vWorldDirection;
  7736. #include <common>
  7737. void main() {
  7738. vec3 direction = normalize( vWorldDirection );
  7739. vec2 sampleUV = equirectUv( direction );
  7740. gl_FragColor = texture2D( tEquirect, sampleUV );
  7741. }
  7742. `
  7743. }
  7744. const geometry = new BoxGeometry(5, 5, 5)
  7745. const material = new ShaderMaterial({
  7746. name: 'CubemapFromEquirect',
  7747. uniforms: cloneUniforms(shader.uniforms),
  7748. vertexShader: shader.vertexShader,
  7749. fragmentShader: shader.fragmentShader,
  7750. side: BackSide,
  7751. blending: NoBlending
  7752. })
  7753. material.uniforms.tEquirect.value = texture
  7754. const mesh = new Mesh(geometry, material)
  7755. const currentMinFilter = texture.minFilter
  7756. // Avoid blurred poles
  7757. if (texture.minFilter === LinearMipmapLinearFilter) texture.minFilter = LinearFilter
  7758. const camera = new CubeCamera(1, 10, this)
  7759. camera.update(renderer, mesh)
  7760. texture.minFilter = currentMinFilter
  7761. mesh.geometry.dispose()
  7762. mesh.material.dispose()
  7763. return this
  7764. }
  7765. clear(renderer, color, depth, stencil) {
  7766. const currentRenderTarget = renderer.getRenderTarget()
  7767. for (let i = 0; i < 6; i++) {
  7768. renderer.setRenderTarget(this, i)
  7769. renderer.clear(color, depth, stencil)
  7770. }
  7771. renderer.setRenderTarget(currentRenderTarget)
  7772. }
  7773. }
  7774. const _vector1 = /*@__PURE__*/ new Vector3()
  7775. const _vector2 = /*@__PURE__*/ new Vector3()
  7776. const _normalMatrix = /*@__PURE__*/ new Matrix3()
  7777. class Plane {
  7778. constructor(normal = new Vector3(1, 0, 0), constant = 0) {
  7779. this.isPlane = true
  7780. // normal is assumed to be normalized
  7781. this.normal = normal
  7782. this.constant = constant
  7783. }
  7784. set(normal, constant) {
  7785. this.normal.copy(normal)
  7786. this.constant = constant
  7787. return this
  7788. }
  7789. setComponents(x, y, z, w) {
  7790. this.normal.set(x, y, z)
  7791. this.constant = w
  7792. return this
  7793. }
  7794. setFromNormalAndCoplanarPoint(normal, point) {
  7795. this.normal.copy(normal)
  7796. this.constant = -point.dot(this.normal)
  7797. return this
  7798. }
  7799. setFromCoplanarPoints(a, b, c) {
  7800. const normal = _vector1
  7801. .subVectors(c, b)
  7802. .cross(_vector2.subVectors(a, b))
  7803. .normalize()
  7804. // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
  7805. this.setFromNormalAndCoplanarPoint(normal, a)
  7806. return this
  7807. }
  7808. copy(plane) {
  7809. this.normal.copy(plane.normal)
  7810. this.constant = plane.constant
  7811. return this
  7812. }
  7813. normalize() {
  7814. // Note: will lead to a divide by zero if the plane is invalid.
  7815. const inverseNormalLength = 1.0 / this.normal.length()
  7816. this.normal.multiplyScalar(inverseNormalLength)
  7817. this.constant *= inverseNormalLength
  7818. return this
  7819. }
  7820. negate() {
  7821. this.constant *= -1
  7822. this.normal.negate()
  7823. return this
  7824. }
  7825. distanceToPoint(point) {
  7826. return this.normal.dot(point) + this.constant
  7827. }
  7828. distanceToSphere(sphere) {
  7829. return this.distanceToPoint(sphere.center) - sphere.radius
  7830. }
  7831. projectPoint(point, target) {
  7832. return target
  7833. .copy(this.normal)
  7834. .multiplyScalar(-this.distanceToPoint(point))
  7835. .add(point)
  7836. }
  7837. intersectLine(line, target) {
  7838. const direction = line.delta(_vector1)
  7839. const denominator = this.normal.dot(direction)
  7840. if (denominator === 0) {
  7841. // line is coplanar, return origin
  7842. if (this.distanceToPoint(line.start) === 0) {
  7843. return target.copy(line.start)
  7844. }
  7845. // Unsure if this is the correct method to handle this case.
  7846. return null
  7847. }
  7848. const t = -(line.start.dot(this.normal) + this.constant) / denominator
  7849. if (t < 0 || t > 1) {
  7850. return null
  7851. }
  7852. return target
  7853. .copy(direction)
  7854. .multiplyScalar(t)
  7855. .add(line.start)
  7856. }
  7857. intersectsLine(line) {
  7858. // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
  7859. const startSign = this.distanceToPoint(line.start)
  7860. const endSign = this.distanceToPoint(line.end)
  7861. return (startSign < 0 && endSign > 0) || (endSign < 0 && startSign > 0)
  7862. }
  7863. intersectsBox(box) {
  7864. return box.intersectsPlane(this)
  7865. }
  7866. intersectsSphere(sphere) {
  7867. return sphere.intersectsPlane(this)
  7868. }
  7869. coplanarPoint(target) {
  7870. return target.copy(this.normal).multiplyScalar(-this.constant)
  7871. }
  7872. applyMatrix4(matrix, optionalNormalMatrix) {
  7873. const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix(matrix)
  7874. const referencePoint = this.coplanarPoint(_vector1).applyMatrix4(matrix)
  7875. const normal = this.normal.applyMatrix3(normalMatrix).normalize()
  7876. this.constant = -referencePoint.dot(normal)
  7877. return this
  7878. }
  7879. translate(offset) {
  7880. this.constant -= offset.dot(this.normal)
  7881. return this
  7882. }
  7883. equals(plane) {
  7884. return plane.normal.equals(this.normal) && plane.constant === this.constant
  7885. }
  7886. clone() {
  7887. return new this.constructor().copy(this)
  7888. }
  7889. }
  7890. const _sphere$2 = /*@__PURE__*/ new Sphere()
  7891. const _vector$7 = /*@__PURE__*/ new Vector3()
  7892. class Frustum {
  7893. constructor(p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane()) {
  7894. this.planes = [p0, p1, p2, p3, p4, p5]
  7895. }
  7896. set(p0, p1, p2, p3, p4, p5) {
  7897. const planes = this.planes
  7898. planes[0].copy(p0)
  7899. planes[1].copy(p1)
  7900. planes[2].copy(p2)
  7901. planes[3].copy(p3)
  7902. planes[4].copy(p4)
  7903. planes[5].copy(p5)
  7904. return this
  7905. }
  7906. copy(frustum) {
  7907. const planes = this.planes
  7908. for (let i = 0; i < 6; i++) {
  7909. planes[i].copy(frustum.planes[i])
  7910. }
  7911. return this
  7912. }
  7913. setFromProjectionMatrix(m) {
  7914. const planes = this.planes
  7915. const me = m.elements
  7916. const me0 = me[0],
  7917. me1 = me[1],
  7918. me2 = me[2],
  7919. me3 = me[3]
  7920. const me4 = me[4],
  7921. me5 = me[5],
  7922. me6 = me[6],
  7923. me7 = me[7]
  7924. const me8 = me[8],
  7925. me9 = me[9],
  7926. me10 = me[10],
  7927. me11 = me[11]
  7928. const me12 = me[12],
  7929. me13 = me[13],
  7930. me14 = me[14],
  7931. me15 = me[15]
  7932. planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize()
  7933. planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize()
  7934. planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize()
  7935. planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize()
  7936. planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize()
  7937. planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize()
  7938. return this
  7939. }
  7940. intersectsObject(object) {
  7941. const geometry = object.geometry
  7942. if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
  7943. _sphere$2.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld)
  7944. return this.intersectsSphere(_sphere$2)
  7945. }
  7946. intersectsSprite(sprite) {
  7947. _sphere$2.center.set(0, 0, 0)
  7948. _sphere$2.radius = 0.7071067811865476
  7949. _sphere$2.applyMatrix4(sprite.matrixWorld)
  7950. return this.intersectsSphere(_sphere$2)
  7951. }
  7952. intersectsSphere(sphere) {
  7953. const planes = this.planes
  7954. const center = sphere.center
  7955. const negRadius = -sphere.radius
  7956. for (let i = 0; i < 6; i++) {
  7957. const distance = planes[i].distanceToPoint(center)
  7958. if (distance < negRadius) {
  7959. return false
  7960. }
  7961. }
  7962. return true
  7963. }
  7964. intersectsBox(box) {
  7965. const planes = this.planes
  7966. for (let i = 0; i < 6; i++) {
  7967. const plane = planes[i]
  7968. // corner at max distance
  7969. _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x
  7970. _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y
  7971. _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z
  7972. if (plane.distanceToPoint(_vector$7) < 0) {
  7973. return false
  7974. }
  7975. }
  7976. return true
  7977. }
  7978. containsPoint(point) {
  7979. const planes = this.planes
  7980. for (let i = 0; i < 6; i++) {
  7981. if (planes[i].distanceToPoint(point) < 0) {
  7982. return false
  7983. }
  7984. }
  7985. return true
  7986. }
  7987. clone() {
  7988. return new this.constructor().copy(this)
  7989. }
  7990. }
  7991. function WebGLAnimation() {
  7992. let context = null
  7993. let isAnimating = false
  7994. let animationLoop = null
  7995. let requestId = null
  7996. function onAnimationFrame(time, frame) {
  7997. animationLoop(time, frame)
  7998. requestId = context.requestAnimationFrame(onAnimationFrame)
  7999. }
  8000. return {
  8001. start: function() {
  8002. if (isAnimating === true) return
  8003. if (animationLoop === null) return
  8004. requestId = context.requestAnimationFrame(onAnimationFrame)
  8005. isAnimating = true
  8006. },
  8007. stop: function() {
  8008. context.cancelAnimationFrame(requestId)
  8009. isAnimating = false
  8010. },
  8011. setAnimationLoop: function(callback) {
  8012. animationLoop = callback
  8013. },
  8014. setContext: function(value) {
  8015. context = value
  8016. }
  8017. }
  8018. }
  8019. function WebGLAttributes(gl, capabilities) {
  8020. const isWebGL2 = capabilities.isWebGL2
  8021. const buffers = new WeakMap()
  8022. function createBuffer(attribute, bufferType) {
  8023. const array = attribute.array
  8024. const usage = attribute.usage
  8025. const buffer = gl.createBuffer()
  8026. gl.bindBuffer(bufferType, buffer)
  8027. gl.bufferData(bufferType, array, usage)
  8028. attribute.onUploadCallback()
  8029. let type
  8030. if (array instanceof Float32Array) {
  8031. type = 5126
  8032. } else if (array instanceof Uint16Array) {
  8033. if (attribute.isFloat16BufferAttribute) {
  8034. if (isWebGL2) {
  8035. type = 5131
  8036. } else {
  8037. throw new Error('THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.')
  8038. }
  8039. } else {
  8040. type = 5123
  8041. }
  8042. } else if (array instanceof Int16Array) {
  8043. type = 5122
  8044. } else if (array instanceof Uint32Array) {
  8045. type = 5125
  8046. } else if (array instanceof Int32Array) {
  8047. type = 5124
  8048. } else if (array instanceof Int8Array) {
  8049. type = 5120
  8050. } else if (array instanceof Uint8Array) {
  8051. type = 5121
  8052. } else if (array instanceof Uint8ClampedArray) {
  8053. type = 5121
  8054. } else {
  8055. throw new Error('THREE.WebGLAttributes: Unsupported buffer data format: ' + array)
  8056. }
  8057. return {
  8058. buffer: buffer,
  8059. type: type,
  8060. bytesPerElement: array.BYTES_PER_ELEMENT,
  8061. version: attribute.version
  8062. }
  8063. }
  8064. function updateBuffer(buffer, attribute, bufferType) {
  8065. const array = attribute.array
  8066. const updateRange = attribute.updateRange
  8067. gl.bindBuffer(bufferType, buffer)
  8068. if (updateRange.count === -1) {
  8069. // Not using update ranges
  8070. gl.bufferSubData(bufferType, 0, array)
  8071. } else {
  8072. if (isWebGL2) {
  8073. gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, array, updateRange.offset, updateRange.count)
  8074. } else {
  8075. gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, array.subarray(updateRange.offset, updateRange.offset + updateRange.count))
  8076. }
  8077. updateRange.count = -1 // reset range
  8078. }
  8079. }
  8080. //
  8081. function get(attribute) {
  8082. if (attribute.isInterleavedBufferAttribute) attribute = attribute.data
  8083. return buffers.get(attribute)
  8084. }
  8085. function remove(attribute) {
  8086. if (attribute.isInterleavedBufferAttribute) attribute = attribute.data
  8087. const data = buffers.get(attribute)
  8088. if (data) {
  8089. gl.deleteBuffer(data.buffer)
  8090. buffers.delete(attribute)
  8091. }
  8092. }
  8093. function update(attribute, bufferType) {
  8094. if (attribute.isGLBufferAttribute) {
  8095. const cached = buffers.get(attribute)
  8096. if (!cached || cached.version < attribute.version) {
  8097. buffers.set(attribute, {
  8098. buffer: attribute.buffer,
  8099. type: attribute.type,
  8100. bytesPerElement: attribute.elementSize,
  8101. version: attribute.version
  8102. })
  8103. }
  8104. return
  8105. }
  8106. if (attribute.isInterleavedBufferAttribute) attribute = attribute.data
  8107. const data = buffers.get(attribute)
  8108. if (data === undefined) {
  8109. buffers.set(attribute, createBuffer(attribute, bufferType))
  8110. } else if (data.version < attribute.version) {
  8111. updateBuffer(data.buffer, attribute, bufferType)
  8112. data.version = attribute.version
  8113. }
  8114. }
  8115. return {
  8116. get: get,
  8117. remove: remove,
  8118. update: update
  8119. }
  8120. }
  8121. class PlaneGeometry extends BufferGeometry {
  8122. constructor(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
  8123. super()
  8124. this.type = 'PlaneGeometry'
  8125. this.parameters = {
  8126. width: width,
  8127. height: height,
  8128. widthSegments: widthSegments,
  8129. heightSegments: heightSegments
  8130. }
  8131. const width_half = width / 2
  8132. const height_half = height / 2
  8133. const gridX = Math.floor(widthSegments)
  8134. const gridY = Math.floor(heightSegments)
  8135. const gridX1 = gridX + 1
  8136. const gridY1 = gridY + 1
  8137. const segment_width = width / gridX
  8138. const segment_height = height / gridY
  8139. //
  8140. const indices = []
  8141. const vertices = []
  8142. const normals = []
  8143. const uvs = []
  8144. for (let iy = 0; iy < gridY1; iy++) {
  8145. const y = iy * segment_height - height_half
  8146. for (let ix = 0; ix < gridX1; ix++) {
  8147. const x = ix * segment_width - width_half
  8148. vertices.push(x, -y, 0)
  8149. normals.push(0, 0, 1)
  8150. uvs.push(ix / gridX)
  8151. uvs.push(1 - iy / gridY)
  8152. }
  8153. }
  8154. for (let iy = 0; iy < gridY; iy++) {
  8155. for (let ix = 0; ix < gridX; ix++) {
  8156. const a = ix + gridX1 * iy
  8157. const b = ix + gridX1 * (iy + 1)
  8158. const c = ix + 1 + gridX1 * (iy + 1)
  8159. const d = ix + 1 + gridX1 * iy
  8160. indices.push(a, b, d)
  8161. indices.push(b, c, d)
  8162. }
  8163. }
  8164. this.setIndex(indices)
  8165. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  8166. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  8167. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  8168. }
  8169. static fromJSON(data) {
  8170. return new PlaneGeometry(data.width, data.height, data.widthSegments, data.heightSegments)
  8171. }
  8172. }
  8173. var alphamap_fragment = '#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif'
  8174. var alphamap_pars_fragment = '#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif'
  8175. var alphatest_fragment = '#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif'
  8176. var alphatest_pars_fragment = '#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif'
  8177. var aomap_fragment =
  8178. '#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif'
  8179. var aomap_pars_fragment = '#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif'
  8180. var begin_vertex = 'vec3 transformed = vec3( position );'
  8181. var beginnormal_vertex = 'vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif'
  8182. var bsdfs =
  8183. 'vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\nvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = mix(F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence);\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif'
  8184. var iridescence_fragment =
  8185. '#ifdef USE_IRIDESCENCE\nconst mat3 XYZ_TO_REC709 = mat3(\n 3.2404542, -0.9692660, 0.0556434,\n -1.5371385, 1.8760108, -0.2040259,\n -0.4985314, 0.0415560, 1.0572252\n);\nvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n vec3 sqrtF0 = sqrt( fresnel0 );\n return ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n}\nvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n}\nfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n return pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n}\nvec3 evalSensitivity( float OPD, vec3 shift ) {\n float phase = 2.0 * PI * OPD * 1.0e-9;\n vec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n vec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n vec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n vec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( -pow2( phase ) * var );\n xyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[0] ) * exp( -4.5282e+09 * pow2( phase ) );\n xyz /= 1.0685e-7;\n vec3 srgb = XYZ_TO_REC709 * xyz;\n return srgb;\n}\nvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n vec3 I;\n float iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n float sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n float cosTheta2Sq = 1.0 - sinTheta2Sq;\n if ( cosTheta2Sq < 0.0 ) {\n return vec3( 1.0 );\n }\n float cosTheta2 = sqrt( cosTheta2Sq );\n float R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n float R12 = F_Schlick( R0, 1.0, cosTheta1 );\n float R21 = R12;\n float T121 = 1.0 - R12;\n float phi12 = 0.0;\n if ( iridescenceIOR < outsideIOR ) phi12 = PI;\n float phi21 = PI - phi12;\n vec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) ); vec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n vec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n vec3 phi23 = vec3( 0.0 );\n if ( baseIOR[0] < iridescenceIOR ) phi23[0] = PI;\n if ( baseIOR[1] < iridescenceIOR ) phi23[1] = PI;\n if ( baseIOR[2] < iridescenceIOR ) phi23[2] = PI;\n float OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n vec3 phi = vec3( phi21 ) + phi23;\n vec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n vec3 r123 = sqrt( R123 );\n vec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n vec3 C0 = R12 + Rs;\n I = C0;\n vec3 Cm = Rs - T121;\n for ( int m = 1; m <= 2; ++m ) {\n Cm *= r123;\n vec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n I += Cm * Sm;\n }\n return max( I, vec3( 0.0 ) );\n}\n#endif'
  8186. var bumpmap_pars_fragment =
  8187. '#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif'
  8188. var clipping_planes_fragment =
  8189. '#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif'
  8190. var clipping_planes_pars_fragment = '#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif'
  8191. var clipping_planes_pars_vertex = '#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif'
  8192. var clipping_planes_vertex = '#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif'
  8193. var color_fragment = '#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif'
  8194. var color_pars_fragment = '#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif'
  8195. var color_pars_vertex = '#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif'
  8196. var color_vertex =
  8197. '#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif'
  8198. var common =
  8199. '#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}'
  8200. var cube_uv_reflection_fragment =
  8201. '#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\tvec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define r0 1.0\n\t#define v0 0.339\n\t#define m0 - 2.0\n\t#define r1 0.8\n\t#define v1 0.276\n\t#define m1 - 1.0\n\t#define r4 0.4\n\t#define v4 0.046\n\t#define m4 2.0\n\t#define r5 0.305\n\t#define v5 0.016\n\t#define m5 3.0\n\t#define r6 0.21\n\t#define v6 0.0038\n\t#define m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= r1 ) {\n\t\t\tmip = ( r0 - roughness ) * ( m1 - m0 ) / ( r0 - r1 ) + m0;\n\t\t} else if ( roughness >= r4 ) {\n\t\t\tmip = ( r1 - roughness ) * ( m4 - m1 ) / ( r1 - r4 ) + m1;\n\t\t} else if ( roughness >= r5 ) {\n\t\t\tmip = ( r4 - roughness ) * ( m5 - m4 ) / ( r4 - r5 ) + m4;\n\t\t} else if ( roughness >= r6 ) {\n\t\t\tmip = ( r5 - roughness ) * ( m6 - m5 ) / ( r5 - r6 ) + m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif'
  8202. var defaultnormal_vertex =
  8203. 'vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif'
  8204. var displacementmap_pars_vertex = '#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif'
  8205. var displacementmap_vertex = '#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif'
  8206. var emissivemap_fragment = '#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif'
  8207. var emissivemap_pars_fragment = '#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif'
  8208. var encodings_fragment = 'gl_FragColor = linearToOutputTexel( gl_FragColor );'
  8209. var encodings_pars_fragment =
  8210. 'vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}'
  8211. var envmap_fragment =
  8212. '#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif'
  8213. var envmap_common_pars_fragment =
  8214. '#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif'
  8215. var envmap_pars_fragment =
  8216. '#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif'
  8217. var envmap_pars_vertex =
  8218. '#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif'
  8219. var envmap_vertex =
  8220. '#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif'
  8221. var fog_vertex = '#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif'
  8222. var fog_pars_vertex = '#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif'
  8223. var fog_fragment =
  8224. '#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif'
  8225. var fog_pars_fragment =
  8226. '#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif'
  8227. var gradientmap_pars_fragment =
  8228. '#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}'
  8229. var lightmap_fragment =
  8230. '#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif'
  8231. var lightmap_pars_fragment = '#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif'
  8232. var lights_lambert_vertex =
  8233. 'vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointLightInfo( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotLightInfo( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalLightInfo( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( - dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif'
  8234. var lights_pars_begin =
  8235. 'uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#else\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif'
  8236. var envmap_physical_pars_fragment =
  8237. '#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif'
  8238. var lights_toon_fragment = 'ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;'
  8239. var lights_toon_pars_fragment =
  8240. 'varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)'
  8241. var lights_phong_fragment =
  8242. 'BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;'
  8243. var lights_phong_pars_fragment =
  8244. 'varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)'
  8245. var lights_physical_fragment =
  8246. 'PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( ior - 1.0 ) / ( ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif'
  8247. var lights_physical_pars_fragment =
  8248. 'struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}'
  8249. var lights_fragment_begin =
  8250. '\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\nfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\nif ( material.iridescenceThickness == 0.0 ) {\n\tmaterial.iridescence = 0.0;\n} else {\n\tmaterial.iridescence = saturate( material.iridescence );\n}\nif ( material.iridescence > 0.0 ) {\n\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif'
  8251. var lights_fragment_maps =
  8252. '#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif'
  8253. var lights_fragment_end =
  8254. '#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif'
  8255. var logdepthbuf_fragment =
  8256. '#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif'
  8257. var logdepthbuf_pars_fragment = '#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif'
  8258. var logdepthbuf_pars_vertex =
  8259. '#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif'
  8260. var logdepthbuf_vertex =
  8261. '#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif'
  8262. var map_fragment =
  8263. '#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif'
  8264. var map_pars_fragment = '#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif'
  8265. var map_particle_fragment =
  8266. '#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif'
  8267. var map_particle_pars_fragment =
  8268. '#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif'
  8269. var metalnessmap_fragment = 'float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif'
  8270. var metalnessmap_pars_fragment = '#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif'
  8271. var morphcolor_vertex =
  8272. '#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif'
  8273. var morphnormal_vertex =
  8274. '#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif'
  8275. var morphtarget_pars_vertex =
  8276. '#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif'
  8277. var morphtarget_vertex =
  8278. '#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif'
  8279. var normal_fragment_begin =
  8280. 'float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;'
  8281. var normal_fragment_maps =
  8282. '#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif'
  8283. var normal_pars_fragment = '#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif'
  8284. var normal_pars_vertex = '#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif'
  8285. var normal_vertex =
  8286. '#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif'
  8287. var normalmap_pars_fragment =
  8288. '#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif'
  8289. var clearcoat_normal_fragment_begin = '#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif'
  8290. var clearcoat_normal_fragment_maps =
  8291. '#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif'
  8292. var clearcoat_pars_fragment =
  8293. '#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif'
  8294. var iridescence_pars_fragment = '#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif'
  8295. var output_fragment = '#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );'
  8296. var packing =
  8297. 'vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}'
  8298. var premultiplied_alpha_fragment = '#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif'
  8299. var project_vertex =
  8300. 'vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;'
  8301. var dithering_fragment = '#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif'
  8302. var dithering_pars_fragment =
  8303. '#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif'
  8304. var roughnessmap_fragment = 'float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif'
  8305. var roughnessmap_pars_fragment = '#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif'
  8306. var shadowmap_pars_fragment =
  8307. '#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif'
  8308. var shadowmap_pars_vertex =
  8309. '#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif'
  8310. var shadowmap_vertex =
  8311. '#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0 || NUM_SPOT_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0\n\t\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\tvec4 shadowWorldPosition;\n\t#endif\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif'
  8312. var shadowmask_pars_fragment =
  8313. 'float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}'
  8314. var skinbase_vertex =
  8315. '#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif'
  8316. var skinning_pars_vertex =
  8317. '#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tuniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif'
  8318. var skinning_vertex =
  8319. '#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif'
  8320. var skinnormal_vertex =
  8321. '#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif'
  8322. var specularmap_fragment =
  8323. 'float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif'
  8324. var specularmap_pars_fragment = '#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif'
  8325. var tonemapping_fragment = '#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif'
  8326. var tonemapping_pars_fragment =
  8327. '#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }'
  8328. var transmission_fragment =
  8329. '#ifdef USE_TRANSMISSION\n\tfloat transmissionAlpha = 1.0;\n\tfloat transmissionFactor = transmission;\n\tfloat thicknessFactor = thickness;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\ttransmissionFactor *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tthicknessFactor *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, roughnessFactor, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, ior, thicknessFactor,\n\t\tattenuationColor, attenuationDistance );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, transmissionFactor );\n\ttransmissionAlpha = mix( transmissionAlpha, transmission.a, transmissionFactor );\n#endif'
  8330. var transmission_pars_fragment =
  8331. '#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\t#ifdef texture2DLodEXT\n\t\t\treturn texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#else\n\t\t\treturn texture2D( transmissionSamplerMap, fragCoord.xy, framebufferLod );\n\t\t#endif\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( attenuationDistance == 0.0 ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif'
  8332. var uv_pars_fragment = '#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif'
  8333. var uv_pars_vertex = '#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif'
  8334. var uv_vertex = '#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif'
  8335. var uv2_pars_fragment = '#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif'
  8336. var uv2_pars_vertex = '#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif'
  8337. var uv2_vertex = '#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif'
  8338. var worldpos_vertex =
  8339. '#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif'
  8340. const vertex$g = 'varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}'
  8341. const fragment$g =
  8342. 'uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tgl_FragColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tgl_FragColor = vec4( mix( pow( gl_FragColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), gl_FragColor.rgb * 0.0773993808, vec3( lessThanEqual( gl_FragColor.rgb, vec3( 0.04045 ) ) ) ), gl_FragColor.w );\n\t#endif\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}'
  8343. const vertex$f =
  8344. 'varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}'
  8345. const fragment$f =
  8346. '#include <envmap_common_pars_fragment>\nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include <envmap_fragment>\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}'
  8347. const vertex$e =
  8348. '#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}'
  8349. const fragment$e =
  8350. '#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}'
  8351. const vertex$d =
  8352. '#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}'
  8353. const fragment$d =
  8354. '#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}'
  8355. const vertex$c =
  8356. 'varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}'
  8357. const fragment$c =
  8358. 'uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}'
  8359. const vertex$b =
  8360. 'uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}'
  8361. const fragment$b =
  8362. 'uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}'
  8363. const vertex$a =
  8364. '#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}'
  8365. const fragment$a =
  8366. 'uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8367. const vertex$9 =
  8368. '#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}'
  8369. const fragment$9 =
  8370. 'uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8371. const vertex$8 =
  8372. '#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}'
  8373. const fragment$8 =
  8374. '#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8375. const vertex$7 =
  8376. '#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}'
  8377. const fragment$7 =
  8378. '#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}'
  8379. const vertex$6 =
  8380. '#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}'
  8381. const fragment$6 =
  8382. '#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8383. const vertex$5 =
  8384. '#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}'
  8385. const fragment$5 =
  8386. '#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <bsdfs>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8387. const vertex$4 =
  8388. '#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}'
  8389. const fragment$4 =
  8390. '#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}'
  8391. const vertex$3 =
  8392. 'uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}'
  8393. const fragment$3 =
  8394. 'uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}'
  8395. const vertex$2 =
  8396. '#include <common>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}'
  8397. const fragment$2 =
  8398. 'uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}'
  8399. const vertex$1 =
  8400. 'uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}'
  8401. const fragment$1 =
  8402. 'uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}'
  8403. const ShaderChunk = {
  8404. alphamap_fragment: alphamap_fragment,
  8405. alphamap_pars_fragment: alphamap_pars_fragment,
  8406. alphatest_fragment: alphatest_fragment,
  8407. alphatest_pars_fragment: alphatest_pars_fragment,
  8408. aomap_fragment: aomap_fragment,
  8409. aomap_pars_fragment: aomap_pars_fragment,
  8410. begin_vertex: begin_vertex,
  8411. beginnormal_vertex: beginnormal_vertex,
  8412. bsdfs: bsdfs,
  8413. iridescence_fragment: iridescence_fragment,
  8414. bumpmap_pars_fragment: bumpmap_pars_fragment,
  8415. clipping_planes_fragment: clipping_planes_fragment,
  8416. clipping_planes_pars_fragment: clipping_planes_pars_fragment,
  8417. clipping_planes_pars_vertex: clipping_planes_pars_vertex,
  8418. clipping_planes_vertex: clipping_planes_vertex,
  8419. color_fragment: color_fragment,
  8420. color_pars_fragment: color_pars_fragment,
  8421. color_pars_vertex: color_pars_vertex,
  8422. color_vertex: color_vertex,
  8423. common: common,
  8424. cube_uv_reflection_fragment: cube_uv_reflection_fragment,
  8425. defaultnormal_vertex: defaultnormal_vertex,
  8426. displacementmap_pars_vertex: displacementmap_pars_vertex,
  8427. displacementmap_vertex: displacementmap_vertex,
  8428. emissivemap_fragment: emissivemap_fragment,
  8429. emissivemap_pars_fragment: emissivemap_pars_fragment,
  8430. encodings_fragment: encodings_fragment,
  8431. encodings_pars_fragment: encodings_pars_fragment,
  8432. envmap_fragment: envmap_fragment,
  8433. envmap_common_pars_fragment: envmap_common_pars_fragment,
  8434. envmap_pars_fragment: envmap_pars_fragment,
  8435. envmap_pars_vertex: envmap_pars_vertex,
  8436. envmap_physical_pars_fragment: envmap_physical_pars_fragment,
  8437. envmap_vertex: envmap_vertex,
  8438. fog_vertex: fog_vertex,
  8439. fog_pars_vertex: fog_pars_vertex,
  8440. fog_fragment: fog_fragment,
  8441. fog_pars_fragment: fog_pars_fragment,
  8442. gradientmap_pars_fragment: gradientmap_pars_fragment,
  8443. lightmap_fragment: lightmap_fragment,
  8444. lightmap_pars_fragment: lightmap_pars_fragment,
  8445. lights_lambert_vertex: lights_lambert_vertex,
  8446. lights_pars_begin: lights_pars_begin,
  8447. lights_toon_fragment: lights_toon_fragment,
  8448. lights_toon_pars_fragment: lights_toon_pars_fragment,
  8449. lights_phong_fragment: lights_phong_fragment,
  8450. lights_phong_pars_fragment: lights_phong_pars_fragment,
  8451. lights_physical_fragment: lights_physical_fragment,
  8452. lights_physical_pars_fragment: lights_physical_pars_fragment,
  8453. lights_fragment_begin: lights_fragment_begin,
  8454. lights_fragment_maps: lights_fragment_maps,
  8455. lights_fragment_end: lights_fragment_end,
  8456. logdepthbuf_fragment: logdepthbuf_fragment,
  8457. logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
  8458. logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
  8459. logdepthbuf_vertex: logdepthbuf_vertex,
  8460. map_fragment: map_fragment,
  8461. map_pars_fragment: map_pars_fragment,
  8462. map_particle_fragment: map_particle_fragment,
  8463. map_particle_pars_fragment: map_particle_pars_fragment,
  8464. metalnessmap_fragment: metalnessmap_fragment,
  8465. metalnessmap_pars_fragment: metalnessmap_pars_fragment,
  8466. morphcolor_vertex: morphcolor_vertex,
  8467. morphnormal_vertex: morphnormal_vertex,
  8468. morphtarget_pars_vertex: morphtarget_pars_vertex,
  8469. morphtarget_vertex: morphtarget_vertex,
  8470. normal_fragment_begin: normal_fragment_begin,
  8471. normal_fragment_maps: normal_fragment_maps,
  8472. normal_pars_fragment: normal_pars_fragment,
  8473. normal_pars_vertex: normal_pars_vertex,
  8474. normal_vertex: normal_vertex,
  8475. normalmap_pars_fragment: normalmap_pars_fragment,
  8476. clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
  8477. clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
  8478. clearcoat_pars_fragment: clearcoat_pars_fragment,
  8479. iridescence_pars_fragment: iridescence_pars_fragment,
  8480. output_fragment: output_fragment,
  8481. packing: packing,
  8482. premultiplied_alpha_fragment: premultiplied_alpha_fragment,
  8483. project_vertex: project_vertex,
  8484. dithering_fragment: dithering_fragment,
  8485. dithering_pars_fragment: dithering_pars_fragment,
  8486. roughnessmap_fragment: roughnessmap_fragment,
  8487. roughnessmap_pars_fragment: roughnessmap_pars_fragment,
  8488. shadowmap_pars_fragment: shadowmap_pars_fragment,
  8489. shadowmap_pars_vertex: shadowmap_pars_vertex,
  8490. shadowmap_vertex: shadowmap_vertex,
  8491. shadowmask_pars_fragment: shadowmask_pars_fragment,
  8492. skinbase_vertex: skinbase_vertex,
  8493. skinning_pars_vertex: skinning_pars_vertex,
  8494. skinning_vertex: skinning_vertex,
  8495. skinnormal_vertex: skinnormal_vertex,
  8496. specularmap_fragment: specularmap_fragment,
  8497. specularmap_pars_fragment: specularmap_pars_fragment,
  8498. tonemapping_fragment: tonemapping_fragment,
  8499. tonemapping_pars_fragment: tonemapping_pars_fragment,
  8500. transmission_fragment: transmission_fragment,
  8501. transmission_pars_fragment: transmission_pars_fragment,
  8502. uv_pars_fragment: uv_pars_fragment,
  8503. uv_pars_vertex: uv_pars_vertex,
  8504. uv_vertex: uv_vertex,
  8505. uv2_pars_fragment: uv2_pars_fragment,
  8506. uv2_pars_vertex: uv2_pars_vertex,
  8507. uv2_vertex: uv2_vertex,
  8508. worldpos_vertex: worldpos_vertex,
  8509. background_vert: vertex$g,
  8510. background_frag: fragment$g,
  8511. cube_vert: vertex$f,
  8512. cube_frag: fragment$f,
  8513. depth_vert: vertex$e,
  8514. depth_frag: fragment$e,
  8515. distanceRGBA_vert: vertex$d,
  8516. distanceRGBA_frag: fragment$d,
  8517. equirect_vert: vertex$c,
  8518. equirect_frag: fragment$c,
  8519. linedashed_vert: vertex$b,
  8520. linedashed_frag: fragment$b,
  8521. meshbasic_vert: vertex$a,
  8522. meshbasic_frag: fragment$a,
  8523. meshlambert_vert: vertex$9,
  8524. meshlambert_frag: fragment$9,
  8525. meshmatcap_vert: vertex$8,
  8526. meshmatcap_frag: fragment$8,
  8527. meshnormal_vert: vertex$7,
  8528. meshnormal_frag: fragment$7,
  8529. meshphong_vert: vertex$6,
  8530. meshphong_frag: fragment$6,
  8531. meshphysical_vert: vertex$5,
  8532. meshphysical_frag: fragment$5,
  8533. meshtoon_vert: vertex$4,
  8534. meshtoon_frag: fragment$4,
  8535. points_vert: vertex$3,
  8536. points_frag: fragment$3,
  8537. shadow_vert: vertex$2,
  8538. shadow_frag: fragment$2,
  8539. sprite_vert: vertex$1,
  8540. sprite_frag: fragment$1
  8541. }
  8542. /**
  8543. * Uniforms library for shared webgl shaders
  8544. */
  8545. const UniformsLib = {
  8546. common: {
  8547. diffuse: { value: new Color(0xffffff) },
  8548. opacity: { value: 1.0 },
  8549. map: { value: null },
  8550. uvTransform: { value: new Matrix3() },
  8551. uv2Transform: { value: new Matrix3() },
  8552. alphaMap: { value: null },
  8553. alphaTest: { value: 0 }
  8554. },
  8555. specularmap: {
  8556. specularMap: { value: null }
  8557. },
  8558. envmap: {
  8559. envMap: { value: null },
  8560. flipEnvMap: { value: -1 },
  8561. reflectivity: { value: 1.0 }, // basic, lambert, phong
  8562. ior: { value: 1.5 }, // physical
  8563. refractionRatio: { value: 0.98 } // basic, lambert, phong
  8564. },
  8565. aomap: {
  8566. aoMap: { value: null },
  8567. aoMapIntensity: { value: 1 }
  8568. },
  8569. lightmap: {
  8570. lightMap: { value: null },
  8571. lightMapIntensity: { value: 1 }
  8572. },
  8573. emissivemap: {
  8574. emissiveMap: { value: null }
  8575. },
  8576. bumpmap: {
  8577. bumpMap: { value: null },
  8578. bumpScale: { value: 1 }
  8579. },
  8580. normalmap: {
  8581. normalMap: { value: null },
  8582. normalScale: { value: new Vector2(1, 1) }
  8583. },
  8584. displacementmap: {
  8585. displacementMap: { value: null },
  8586. displacementScale: { value: 1 },
  8587. displacementBias: { value: 0 }
  8588. },
  8589. roughnessmap: {
  8590. roughnessMap: { value: null }
  8591. },
  8592. metalnessmap: {
  8593. metalnessMap: { value: null }
  8594. },
  8595. gradientmap: {
  8596. gradientMap: { value: null }
  8597. },
  8598. fog: {
  8599. fogDensity: { value: 0.00025 },
  8600. fogNear: { value: 1 },
  8601. fogFar: { value: 2000 },
  8602. fogColor: { value: new Color(0xffffff) }
  8603. },
  8604. lights: {
  8605. ambientLightColor: { value: [] },
  8606. lightProbe: { value: [] },
  8607. directionalLights: {
  8608. value: [],
  8609. properties: {
  8610. direction: {},
  8611. color: {}
  8612. }
  8613. },
  8614. directionalLightShadows: {
  8615. value: [],
  8616. properties: {
  8617. shadowBias: {},
  8618. shadowNormalBias: {},
  8619. shadowRadius: {},
  8620. shadowMapSize: {}
  8621. }
  8622. },
  8623. directionalShadowMap: { value: [] },
  8624. directionalShadowMatrix: { value: [] },
  8625. spotLights: {
  8626. value: [],
  8627. properties: {
  8628. color: {},
  8629. position: {},
  8630. direction: {},
  8631. distance: {},
  8632. coneCos: {},
  8633. penumbraCos: {},
  8634. decay: {}
  8635. }
  8636. },
  8637. spotLightShadows: {
  8638. value: [],
  8639. properties: {
  8640. shadowBias: {},
  8641. shadowNormalBias: {},
  8642. shadowRadius: {},
  8643. shadowMapSize: {}
  8644. }
  8645. },
  8646. spotShadowMap: { value: [] },
  8647. spotShadowMatrix: { value: [] },
  8648. pointLights: {
  8649. value: [],
  8650. properties: {
  8651. color: {},
  8652. position: {},
  8653. decay: {},
  8654. distance: {}
  8655. }
  8656. },
  8657. pointLightShadows: {
  8658. value: [],
  8659. properties: {
  8660. shadowBias: {},
  8661. shadowNormalBias: {},
  8662. shadowRadius: {},
  8663. shadowMapSize: {},
  8664. shadowCameraNear: {},
  8665. shadowCameraFar: {}
  8666. }
  8667. },
  8668. pointShadowMap: { value: [] },
  8669. pointShadowMatrix: { value: [] },
  8670. hemisphereLights: {
  8671. value: [],
  8672. properties: {
  8673. direction: {},
  8674. skyColor: {},
  8675. groundColor: {}
  8676. }
  8677. },
  8678. // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
  8679. rectAreaLights: {
  8680. value: [],
  8681. properties: {
  8682. color: {},
  8683. position: {},
  8684. width: {},
  8685. height: {}
  8686. }
  8687. },
  8688. ltc_1: { value: null },
  8689. ltc_2: { value: null }
  8690. },
  8691. points: {
  8692. diffuse: { value: new Color(0xffffff) },
  8693. opacity: { value: 1.0 },
  8694. size: { value: 1.0 },
  8695. scale: { value: 1.0 },
  8696. map: { value: null },
  8697. alphaMap: { value: null },
  8698. alphaTest: { value: 0 },
  8699. uvTransform: { value: new Matrix3() }
  8700. },
  8701. sprite: {
  8702. diffuse: { value: new Color(0xffffff) },
  8703. opacity: { value: 1.0 },
  8704. center: { value: new Vector2(0.5, 0.5) },
  8705. rotation: { value: 0.0 },
  8706. map: { value: null },
  8707. alphaMap: { value: null },
  8708. alphaTest: { value: 0 },
  8709. uvTransform: { value: new Matrix3() }
  8710. }
  8711. }
  8712. const ShaderLib = {
  8713. basic: {
  8714. uniforms: mergeUniforms([UniformsLib.common, UniformsLib.specularmap, UniformsLib.envmap, UniformsLib.aomap, UniformsLib.lightmap, UniformsLib.fog]),
  8715. vertexShader: ShaderChunk.meshbasic_vert,
  8716. fragmentShader: ShaderChunk.meshbasic_frag
  8717. },
  8718. lambert: {
  8719. uniforms: mergeUniforms([
  8720. UniformsLib.common,
  8721. UniformsLib.specularmap,
  8722. UniformsLib.envmap,
  8723. UniformsLib.aomap,
  8724. UniformsLib.lightmap,
  8725. UniformsLib.emissivemap,
  8726. UniformsLib.fog,
  8727. UniformsLib.lights,
  8728. {
  8729. emissive: { value: new Color(0x000000) }
  8730. }
  8731. ]),
  8732. vertexShader: ShaderChunk.meshlambert_vert,
  8733. fragmentShader: ShaderChunk.meshlambert_frag
  8734. },
  8735. phong: {
  8736. uniforms: mergeUniforms([
  8737. UniformsLib.common,
  8738. UniformsLib.specularmap,
  8739. UniformsLib.envmap,
  8740. UniformsLib.aomap,
  8741. UniformsLib.lightmap,
  8742. UniformsLib.emissivemap,
  8743. UniformsLib.bumpmap,
  8744. UniformsLib.normalmap,
  8745. UniformsLib.displacementmap,
  8746. UniformsLib.fog,
  8747. UniformsLib.lights,
  8748. {
  8749. emissive: { value: new Color(0x000000) },
  8750. specular: { value: new Color(0x111111) },
  8751. shininess: { value: 30 }
  8752. }
  8753. ]),
  8754. vertexShader: ShaderChunk.meshphong_vert,
  8755. fragmentShader: ShaderChunk.meshphong_frag
  8756. },
  8757. standard: {
  8758. uniforms: mergeUniforms([
  8759. UniformsLib.common,
  8760. UniformsLib.envmap,
  8761. UniformsLib.aomap,
  8762. UniformsLib.lightmap,
  8763. UniformsLib.emissivemap,
  8764. UniformsLib.bumpmap,
  8765. UniformsLib.normalmap,
  8766. UniformsLib.displacementmap,
  8767. UniformsLib.roughnessmap,
  8768. UniformsLib.metalnessmap,
  8769. UniformsLib.fog,
  8770. UniformsLib.lights,
  8771. {
  8772. emissive: { value: new Color(0x000000) },
  8773. roughness: { value: 1.0 },
  8774. metalness: { value: 0.0 },
  8775. envMapIntensity: { value: 1 } // temporary
  8776. }
  8777. ]),
  8778. vertexShader: ShaderChunk.meshphysical_vert,
  8779. fragmentShader: ShaderChunk.meshphysical_frag
  8780. },
  8781. toon: {
  8782. uniforms: mergeUniforms([
  8783. UniformsLib.common,
  8784. UniformsLib.aomap,
  8785. UniformsLib.lightmap,
  8786. UniformsLib.emissivemap,
  8787. UniformsLib.bumpmap,
  8788. UniformsLib.normalmap,
  8789. UniformsLib.displacementmap,
  8790. UniformsLib.gradientmap,
  8791. UniformsLib.fog,
  8792. UniformsLib.lights,
  8793. {
  8794. emissive: { value: new Color(0x000000) }
  8795. }
  8796. ]),
  8797. vertexShader: ShaderChunk.meshtoon_vert,
  8798. fragmentShader: ShaderChunk.meshtoon_frag
  8799. },
  8800. matcap: {
  8801. uniforms: mergeUniforms([
  8802. UniformsLib.common,
  8803. UniformsLib.bumpmap,
  8804. UniformsLib.normalmap,
  8805. UniformsLib.displacementmap,
  8806. UniformsLib.fog,
  8807. {
  8808. matcap: { value: null }
  8809. }
  8810. ]),
  8811. vertexShader: ShaderChunk.meshmatcap_vert,
  8812. fragmentShader: ShaderChunk.meshmatcap_frag
  8813. },
  8814. points: {
  8815. uniforms: mergeUniforms([UniformsLib.points, UniformsLib.fog]),
  8816. vertexShader: ShaderChunk.points_vert,
  8817. fragmentShader: ShaderChunk.points_frag
  8818. },
  8819. dashed: {
  8820. uniforms: mergeUniforms([
  8821. UniformsLib.common,
  8822. UniformsLib.fog,
  8823. {
  8824. scale: { value: 1 },
  8825. dashSize: { value: 1 },
  8826. totalSize: { value: 2 }
  8827. }
  8828. ]),
  8829. vertexShader: ShaderChunk.linedashed_vert,
  8830. fragmentShader: ShaderChunk.linedashed_frag
  8831. },
  8832. depth: {
  8833. uniforms: mergeUniforms([UniformsLib.common, UniformsLib.displacementmap]),
  8834. vertexShader: ShaderChunk.depth_vert,
  8835. fragmentShader: ShaderChunk.depth_frag
  8836. },
  8837. normal: {
  8838. uniforms: mergeUniforms([
  8839. UniformsLib.common,
  8840. UniformsLib.bumpmap,
  8841. UniformsLib.normalmap,
  8842. UniformsLib.displacementmap,
  8843. {
  8844. opacity: { value: 1.0 }
  8845. }
  8846. ]),
  8847. vertexShader: ShaderChunk.meshnormal_vert,
  8848. fragmentShader: ShaderChunk.meshnormal_frag
  8849. },
  8850. sprite: {
  8851. uniforms: mergeUniforms([UniformsLib.sprite, UniformsLib.fog]),
  8852. vertexShader: ShaderChunk.sprite_vert,
  8853. fragmentShader: ShaderChunk.sprite_frag
  8854. },
  8855. background: {
  8856. uniforms: {
  8857. uvTransform: { value: new Matrix3() },
  8858. t2D: { value: null }
  8859. },
  8860. vertexShader: ShaderChunk.background_vert,
  8861. fragmentShader: ShaderChunk.background_frag
  8862. },
  8863. /* -------------------------------------------------------------------------
  8864. // Cube map shader
  8865. ------------------------------------------------------------------------- */
  8866. cube: {
  8867. uniforms: mergeUniforms([
  8868. UniformsLib.envmap,
  8869. {
  8870. opacity: { value: 1.0 }
  8871. }
  8872. ]),
  8873. vertexShader: ShaderChunk.cube_vert,
  8874. fragmentShader: ShaderChunk.cube_frag
  8875. },
  8876. equirect: {
  8877. uniforms: {
  8878. tEquirect: { value: null }
  8879. },
  8880. vertexShader: ShaderChunk.equirect_vert,
  8881. fragmentShader: ShaderChunk.equirect_frag
  8882. },
  8883. distanceRGBA: {
  8884. uniforms: mergeUniforms([
  8885. UniformsLib.common,
  8886. UniformsLib.displacementmap,
  8887. {
  8888. referencePosition: { value: new Vector3() },
  8889. nearDistance: { value: 1 },
  8890. farDistance: { value: 1000 }
  8891. }
  8892. ]),
  8893. vertexShader: ShaderChunk.distanceRGBA_vert,
  8894. fragmentShader: ShaderChunk.distanceRGBA_frag
  8895. },
  8896. shadow: {
  8897. uniforms: mergeUniforms([
  8898. UniformsLib.lights,
  8899. UniformsLib.fog,
  8900. {
  8901. color: { value: new Color(0x00000) },
  8902. opacity: { value: 1.0 }
  8903. }
  8904. ]),
  8905. vertexShader: ShaderChunk.shadow_vert,
  8906. fragmentShader: ShaderChunk.shadow_frag
  8907. }
  8908. }
  8909. ShaderLib.physical = {
  8910. uniforms: mergeUniforms([
  8911. ShaderLib.standard.uniforms,
  8912. {
  8913. clearcoat: { value: 0 },
  8914. clearcoatMap: { value: null },
  8915. clearcoatRoughness: { value: 0 },
  8916. clearcoatRoughnessMap: { value: null },
  8917. clearcoatNormalScale: { value: new Vector2(1, 1) },
  8918. clearcoatNormalMap: { value: null },
  8919. iridescence: { value: 0 },
  8920. iridescenceMap: { value: null },
  8921. iridescenceIOR: { value: 1.3 },
  8922. iridescenceThicknessMinimum: { value: 100 },
  8923. iridescenceThicknessMaximum: { value: 400 },
  8924. iridescenceThicknessMap: { value: null },
  8925. sheen: { value: 0 },
  8926. sheenColor: { value: new Color(0x000000) },
  8927. sheenColorMap: { value: null },
  8928. sheenRoughness: { value: 1 },
  8929. sheenRoughnessMap: { value: null },
  8930. transmission: { value: 0 },
  8931. transmissionMap: { value: null },
  8932. transmissionSamplerSize: { value: new Vector2() },
  8933. transmissionSamplerMap: { value: null },
  8934. thickness: { value: 0 },
  8935. thicknessMap: { value: null },
  8936. attenuationDistance: { value: 0 },
  8937. attenuationColor: { value: new Color(0x000000) },
  8938. specularIntensity: { value: 1 },
  8939. specularIntensityMap: { value: null },
  8940. specularColor: { value: new Color(1, 1, 1) },
  8941. specularColorMap: { value: null }
  8942. }
  8943. ]),
  8944. vertexShader: ShaderChunk.meshphysical_vert,
  8945. fragmentShader: ShaderChunk.meshphysical_frag
  8946. }
  8947. function WebGLBackground(renderer, cubemaps, state, objects, alpha, premultipliedAlpha) {
  8948. const clearColor = new Color(0x000000)
  8949. let clearAlpha = alpha === true ? 0 : 1
  8950. let planeMesh
  8951. let boxMesh
  8952. let currentBackground = null
  8953. let currentBackgroundVersion = 0
  8954. let currentTonemapping = null
  8955. function render(renderList, scene) {
  8956. let forceClear = false
  8957. let background = scene.isScene === true ? scene.background : null
  8958. if (background && background.isTexture) {
  8959. background = cubemaps.get(background)
  8960. }
  8961. // Ignore background in AR
  8962. // TODO: Reconsider this.
  8963. const xr = renderer.xr
  8964. const session = xr.getSession && xr.getSession()
  8965. if (session && session.environmentBlendMode === 'additive') {
  8966. background = null
  8967. }
  8968. if (background === null) {
  8969. setClear(clearColor, clearAlpha)
  8970. } else if (background && background.isColor) {
  8971. setClear(background, 1)
  8972. forceClear = true
  8973. }
  8974. if (renderer.autoClear || forceClear) {
  8975. renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil)
  8976. }
  8977. if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) {
  8978. if (boxMesh === undefined) {
  8979. boxMesh = new Mesh(
  8980. new BoxGeometry(1, 1, 1),
  8981. new ShaderMaterial({
  8982. name: 'BackgroundCubeMaterial',
  8983. uniforms: cloneUniforms(ShaderLib.cube.uniforms),
  8984. vertexShader: ShaderLib.cube.vertexShader,
  8985. fragmentShader: ShaderLib.cube.fragmentShader,
  8986. side: BackSide,
  8987. depthTest: false,
  8988. depthWrite: false,
  8989. fog: false
  8990. })
  8991. )
  8992. boxMesh.geometry.deleteAttribute('normal')
  8993. boxMesh.geometry.deleteAttribute('uv')
  8994. boxMesh.onBeforeRender = function(renderer, scene, camera) {
  8995. this.matrixWorld.copyPosition(camera.matrixWorld)
  8996. }
  8997. // enable code injection for non-built-in material
  8998. Object.defineProperty(boxMesh.material, 'envMap', {
  8999. get: function() {
  9000. return this.uniforms.envMap.value
  9001. }
  9002. })
  9003. objects.update(boxMesh)
  9004. }
  9005. boxMesh.material.uniforms.envMap.value = background
  9006. boxMesh.material.uniforms.flipEnvMap.value = background.isCubeTexture && background.isRenderTargetTexture === false ? -1 : 1
  9007. if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) {
  9008. boxMesh.material.needsUpdate = true
  9009. currentBackground = background
  9010. currentBackgroundVersion = background.version
  9011. currentTonemapping = renderer.toneMapping
  9012. }
  9013. boxMesh.layers.enableAll()
  9014. // push to the pre-sorted opaque render list
  9015. renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null)
  9016. } else if (background && background.isTexture) {
  9017. if (planeMesh === undefined) {
  9018. planeMesh = new Mesh(
  9019. new PlaneGeometry(2, 2),
  9020. new ShaderMaterial({
  9021. name: 'BackgroundMaterial',
  9022. uniforms: cloneUniforms(ShaderLib.background.uniforms),
  9023. vertexShader: ShaderLib.background.vertexShader,
  9024. fragmentShader: ShaderLib.background.fragmentShader,
  9025. side: FrontSide,
  9026. depthTest: false,
  9027. depthWrite: false,
  9028. fog: false
  9029. })
  9030. )
  9031. planeMesh.geometry.deleteAttribute('normal')
  9032. // enable code injection for non-built-in material
  9033. Object.defineProperty(planeMesh.material, 'map', {
  9034. get: function() {
  9035. return this.uniforms.t2D.value
  9036. }
  9037. })
  9038. objects.update(planeMesh)
  9039. }
  9040. planeMesh.material.uniforms.t2D.value = background
  9041. if (background.matrixAutoUpdate === true) {
  9042. background.updateMatrix()
  9043. }
  9044. planeMesh.material.uniforms.uvTransform.value.copy(background.matrix)
  9045. if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) {
  9046. planeMesh.material.needsUpdate = true
  9047. currentBackground = background
  9048. currentBackgroundVersion = background.version
  9049. currentTonemapping = renderer.toneMapping
  9050. }
  9051. planeMesh.layers.enableAll()
  9052. // push to the pre-sorted opaque render list
  9053. renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null)
  9054. }
  9055. }
  9056. function setClear(color, alpha) {
  9057. state.buffers.color.setClear(color.r, color.g, color.b, alpha, premultipliedAlpha)
  9058. }
  9059. return {
  9060. getClearColor: function() {
  9061. return clearColor
  9062. },
  9063. setClearColor: function(color, alpha = 1) {
  9064. clearColor.set(color)
  9065. clearAlpha = alpha
  9066. setClear(clearColor, clearAlpha)
  9067. },
  9068. getClearAlpha: function() {
  9069. return clearAlpha
  9070. },
  9071. setClearAlpha: function(alpha) {
  9072. clearAlpha = alpha
  9073. setClear(clearColor, clearAlpha)
  9074. },
  9075. render: render
  9076. }
  9077. }
  9078. function WebGLBindingStates(gl, extensions, attributes, capabilities) {
  9079. const maxVertexAttributes = gl.getParameter(34921)
  9080. const extension = capabilities.isWebGL2 ? null : extensions.get('OES_vertex_array_object')
  9081. const vaoAvailable = capabilities.isWebGL2 || extension !== null
  9082. const bindingStates = {}
  9083. const defaultState = createBindingState(null)
  9084. let currentState = defaultState
  9085. let forceUpdate = false
  9086. function setup(object, material, program, geometry, index) {
  9087. let updateBuffers = false
  9088. if (vaoAvailable) {
  9089. const state = getBindingState(geometry, program, material)
  9090. if (currentState !== state) {
  9091. currentState = state
  9092. bindVertexArrayObject(currentState.object)
  9093. }
  9094. updateBuffers = needsUpdate(object, geometry, program, index)
  9095. if (updateBuffers) saveCache(object, geometry, program, index)
  9096. } else {
  9097. const wireframe = material.wireframe === true
  9098. if (currentState.geometry !== geometry.id || currentState.program !== program.id || currentState.wireframe !== wireframe) {
  9099. currentState.geometry = geometry.id
  9100. currentState.program = program.id
  9101. currentState.wireframe = wireframe
  9102. updateBuffers = true
  9103. }
  9104. }
  9105. if (index !== null) {
  9106. attributes.update(index, 34963)
  9107. }
  9108. if (updateBuffers || forceUpdate) {
  9109. forceUpdate = false
  9110. setupVertexAttributes(object, material, program, geometry)
  9111. if (index !== null) {
  9112. gl.bindBuffer(34963, attributes.get(index).buffer)
  9113. }
  9114. }
  9115. }
  9116. function createVertexArrayObject() {
  9117. if (capabilities.isWebGL2) return gl.createVertexArray()
  9118. return extension.createVertexArrayOES()
  9119. }
  9120. function bindVertexArrayObject(vao) {
  9121. if (capabilities.isWebGL2) return gl.bindVertexArray(vao)
  9122. return extension.bindVertexArrayOES(vao)
  9123. }
  9124. function deleteVertexArrayObject(vao) {
  9125. if (capabilities.isWebGL2) return gl.deleteVertexArray(vao)
  9126. return extension.deleteVertexArrayOES(vao)
  9127. }
  9128. function getBindingState(geometry, program, material) {
  9129. const wireframe = material.wireframe === true
  9130. let programMap = bindingStates[geometry.id]
  9131. if (programMap === undefined) {
  9132. programMap = {}
  9133. bindingStates[geometry.id] = programMap
  9134. }
  9135. let stateMap = programMap[program.id]
  9136. if (stateMap === undefined) {
  9137. stateMap = {}
  9138. programMap[program.id] = stateMap
  9139. }
  9140. let state = stateMap[wireframe]
  9141. if (state === undefined) {
  9142. state = createBindingState(createVertexArrayObject())
  9143. stateMap[wireframe] = state
  9144. }
  9145. return state
  9146. }
  9147. function createBindingState(vao) {
  9148. const newAttributes = []
  9149. const enabledAttributes = []
  9150. const attributeDivisors = []
  9151. for (let i = 0; i < maxVertexAttributes; i++) {
  9152. newAttributes[i] = 0
  9153. enabledAttributes[i] = 0
  9154. attributeDivisors[i] = 0
  9155. }
  9156. return {
  9157. // for backward compatibility on non-VAO support browser
  9158. geometry: null,
  9159. program: null,
  9160. wireframe: false,
  9161. newAttributes: newAttributes,
  9162. enabledAttributes: enabledAttributes,
  9163. attributeDivisors: attributeDivisors,
  9164. object: vao,
  9165. attributes: {},
  9166. index: null
  9167. }
  9168. }
  9169. function needsUpdate(object, geometry, program, index) {
  9170. const cachedAttributes = currentState.attributes
  9171. const geometryAttributes = geometry.attributes
  9172. let attributesNum = 0
  9173. const programAttributes = program.getAttributes()
  9174. for (const name in programAttributes) {
  9175. const programAttribute = programAttributes[name]
  9176. if (programAttribute.location >= 0) {
  9177. const cachedAttribute = cachedAttributes[name]
  9178. let geometryAttribute = geometryAttributes[name]
  9179. if (geometryAttribute === undefined) {
  9180. if (name === 'instanceMatrix' && object.instanceMatrix) geometryAttribute = object.instanceMatrix
  9181. if (name === 'instanceColor' && object.instanceColor) geometryAttribute = object.instanceColor
  9182. }
  9183. if (cachedAttribute === undefined) return true
  9184. if (cachedAttribute.attribute !== geometryAttribute) return true
  9185. if (geometryAttribute && cachedAttribute.data !== geometryAttribute.data) return true
  9186. attributesNum++
  9187. }
  9188. }
  9189. if (currentState.attributesNum !== attributesNum) return true
  9190. if (currentState.index !== index) return true
  9191. return false
  9192. }
  9193. function saveCache(object, geometry, program, index) {
  9194. const cache = {}
  9195. const attributes = geometry.attributes
  9196. let attributesNum = 0
  9197. const programAttributes = program.getAttributes()
  9198. for (const name in programAttributes) {
  9199. const programAttribute = programAttributes[name]
  9200. if (programAttribute.location >= 0) {
  9201. let attribute = attributes[name]
  9202. if (attribute === undefined) {
  9203. if (name === 'instanceMatrix' && object.instanceMatrix) attribute = object.instanceMatrix
  9204. if (name === 'instanceColor' && object.instanceColor) attribute = object.instanceColor
  9205. }
  9206. const data = {}
  9207. data.attribute = attribute
  9208. if (attribute && attribute.data) {
  9209. data.data = attribute.data
  9210. }
  9211. cache[name] = data
  9212. attributesNum++
  9213. }
  9214. }
  9215. currentState.attributes = cache
  9216. currentState.attributesNum = attributesNum
  9217. currentState.index = index
  9218. }
  9219. function initAttributes() {
  9220. const newAttributes = currentState.newAttributes
  9221. for (let i = 0, il = newAttributes.length; i < il; i++) {
  9222. newAttributes[i] = 0
  9223. }
  9224. }
  9225. function enableAttribute(attribute) {
  9226. enableAttributeAndDivisor(attribute, 0)
  9227. }
  9228. function enableAttributeAndDivisor(attribute, meshPerAttribute) {
  9229. const newAttributes = currentState.newAttributes
  9230. const enabledAttributes = currentState.enabledAttributes
  9231. const attributeDivisors = currentState.attributeDivisors
  9232. newAttributes[attribute] = 1
  9233. if (enabledAttributes[attribute] === 0) {
  9234. gl.enableVertexAttribArray(attribute)
  9235. enabledAttributes[attribute] = 1
  9236. }
  9237. if (attributeDivisors[attribute] !== meshPerAttribute) {
  9238. const extension = capabilities.isWebGL2 ? gl : extensions.get('ANGLE_instanced_arrays')
  9239. extension[capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE'](attribute, meshPerAttribute)
  9240. attributeDivisors[attribute] = meshPerAttribute
  9241. }
  9242. }
  9243. function disableUnusedAttributes() {
  9244. const newAttributes = currentState.newAttributes
  9245. const enabledAttributes = currentState.enabledAttributes
  9246. for (let i = 0, il = enabledAttributes.length; i < il; i++) {
  9247. if (enabledAttributes[i] !== newAttributes[i]) {
  9248. gl.disableVertexAttribArray(i)
  9249. enabledAttributes[i] = 0
  9250. }
  9251. }
  9252. }
  9253. function vertexAttribPointer(index, size, type, normalized, stride, offset) {
  9254. if (capabilities.isWebGL2 === true && (type === 5124 || type === 5125)) {
  9255. gl.vertexAttribIPointer(index, size, type, stride, offset)
  9256. } else {
  9257. gl.vertexAttribPointer(index, size, type, normalized, stride, offset)
  9258. }
  9259. }
  9260. function setupVertexAttributes(object, material, program, geometry) {
  9261. if (capabilities.isWebGL2 === false && (object.isInstancedMesh || geometry.isInstancedBufferGeometry)) {
  9262. if (extensions.get('ANGLE_instanced_arrays') === null) return
  9263. }
  9264. initAttributes()
  9265. const geometryAttributes = geometry.attributes
  9266. const programAttributes = program.getAttributes()
  9267. const materialDefaultAttributeValues = material.defaultAttributeValues
  9268. for (const name in programAttributes) {
  9269. const programAttribute = programAttributes[name]
  9270. if (programAttribute.location >= 0) {
  9271. let geometryAttribute = geometryAttributes[name]
  9272. if (geometryAttribute === undefined) {
  9273. if (name === 'instanceMatrix' && object.instanceMatrix) geometryAttribute = object.instanceMatrix
  9274. if (name === 'instanceColor' && object.instanceColor) geometryAttribute = object.instanceColor
  9275. }
  9276. if (geometryAttribute !== undefined) {
  9277. const normalized = geometryAttribute.normalized
  9278. const size = geometryAttribute.itemSize
  9279. const attribute = attributes.get(geometryAttribute)
  9280. // TODO Attribute may not be available on context restore
  9281. if (attribute === undefined) continue
  9282. const buffer = attribute.buffer
  9283. const type = attribute.type
  9284. const bytesPerElement = attribute.bytesPerElement
  9285. if (geometryAttribute.isInterleavedBufferAttribute) {
  9286. const data = geometryAttribute.data
  9287. const stride = data.stride
  9288. const offset = geometryAttribute.offset
  9289. if (data.isInstancedInterleavedBuffer) {
  9290. for (let i = 0; i < programAttribute.locationSize; i++) {
  9291. enableAttributeAndDivisor(programAttribute.location + i, data.meshPerAttribute)
  9292. }
  9293. if (object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined) {
  9294. geometry._maxInstanceCount = data.meshPerAttribute * data.count
  9295. }
  9296. } else {
  9297. for (let i = 0; i < programAttribute.locationSize; i++) {
  9298. enableAttribute(programAttribute.location + i)
  9299. }
  9300. }
  9301. gl.bindBuffer(34962, buffer)
  9302. for (let i = 0; i < programAttribute.locationSize; i++) {
  9303. vertexAttribPointer(
  9304. programAttribute.location + i,
  9305. size / programAttribute.locationSize,
  9306. type,
  9307. normalized,
  9308. stride * bytesPerElement,
  9309. (offset + (size / programAttribute.locationSize) * i) * bytesPerElement
  9310. )
  9311. }
  9312. } else {
  9313. if (geometryAttribute.isInstancedBufferAttribute) {
  9314. for (let i = 0; i < programAttribute.locationSize; i++) {
  9315. enableAttributeAndDivisor(programAttribute.location + i, geometryAttribute.meshPerAttribute)
  9316. }
  9317. if (object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined) {
  9318. geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count
  9319. }
  9320. } else {
  9321. for (let i = 0; i < programAttribute.locationSize; i++) {
  9322. enableAttribute(programAttribute.location + i)
  9323. }
  9324. }
  9325. gl.bindBuffer(34962, buffer)
  9326. for (let i = 0; i < programAttribute.locationSize; i++) {
  9327. vertexAttribPointer(
  9328. programAttribute.location + i,
  9329. size / programAttribute.locationSize,
  9330. type,
  9331. normalized,
  9332. size * bytesPerElement,
  9333. (size / programAttribute.locationSize) * i * bytesPerElement
  9334. )
  9335. }
  9336. }
  9337. } else if (materialDefaultAttributeValues !== undefined) {
  9338. const value = materialDefaultAttributeValues[name]
  9339. if (value !== undefined) {
  9340. switch (value.length) {
  9341. case 2:
  9342. gl.vertexAttrib2fv(programAttribute.location, value)
  9343. break
  9344. case 3:
  9345. gl.vertexAttrib3fv(programAttribute.location, value)
  9346. break
  9347. case 4:
  9348. gl.vertexAttrib4fv(programAttribute.location, value)
  9349. break
  9350. default:
  9351. gl.vertexAttrib1fv(programAttribute.location, value)
  9352. }
  9353. }
  9354. }
  9355. }
  9356. }
  9357. disableUnusedAttributes()
  9358. }
  9359. function dispose() {
  9360. reset()
  9361. for (const geometryId in bindingStates) {
  9362. const programMap = bindingStates[geometryId]
  9363. for (const programId in programMap) {
  9364. const stateMap = programMap[programId]
  9365. for (const wireframe in stateMap) {
  9366. deleteVertexArrayObject(stateMap[wireframe].object)
  9367. delete stateMap[wireframe]
  9368. }
  9369. delete programMap[programId]
  9370. }
  9371. delete bindingStates[geometryId]
  9372. }
  9373. }
  9374. function releaseStatesOfGeometry(geometry) {
  9375. if (bindingStates[geometry.id] === undefined) return
  9376. const programMap = bindingStates[geometry.id]
  9377. for (const programId in programMap) {
  9378. const stateMap = programMap[programId]
  9379. for (const wireframe in stateMap) {
  9380. deleteVertexArrayObject(stateMap[wireframe].object)
  9381. delete stateMap[wireframe]
  9382. }
  9383. delete programMap[programId]
  9384. }
  9385. delete bindingStates[geometry.id]
  9386. }
  9387. function releaseStatesOfProgram(program) {
  9388. for (const geometryId in bindingStates) {
  9389. const programMap = bindingStates[geometryId]
  9390. if (programMap[program.id] === undefined) continue
  9391. const stateMap = programMap[program.id]
  9392. for (const wireframe in stateMap) {
  9393. deleteVertexArrayObject(stateMap[wireframe].object)
  9394. delete stateMap[wireframe]
  9395. }
  9396. delete programMap[program.id]
  9397. }
  9398. }
  9399. function reset() {
  9400. resetDefaultState()
  9401. forceUpdate = true
  9402. if (currentState === defaultState) return
  9403. currentState = defaultState
  9404. bindVertexArrayObject(currentState.object)
  9405. }
  9406. // for backward-compatibility
  9407. function resetDefaultState() {
  9408. defaultState.geometry = null
  9409. defaultState.program = null
  9410. defaultState.wireframe = false
  9411. }
  9412. return {
  9413. setup: setup,
  9414. reset: reset,
  9415. resetDefaultState: resetDefaultState,
  9416. dispose: dispose,
  9417. releaseStatesOfGeometry: releaseStatesOfGeometry,
  9418. releaseStatesOfProgram: releaseStatesOfProgram,
  9419. initAttributes: initAttributes,
  9420. enableAttribute: enableAttribute,
  9421. disableUnusedAttributes: disableUnusedAttributes
  9422. }
  9423. }
  9424. function WebGLBufferRenderer(gl, extensions, info, capabilities) {
  9425. const isWebGL2 = capabilities.isWebGL2
  9426. let mode
  9427. function setMode(value) {
  9428. mode = value
  9429. }
  9430. function render(start, count) {
  9431. gl.drawArrays(mode, start, count)
  9432. info.update(count, mode, 1)
  9433. }
  9434. function renderInstances(start, count, primcount) {
  9435. if (primcount === 0) return
  9436. let extension, methodName
  9437. if (isWebGL2) {
  9438. extension = gl
  9439. methodName = 'drawArraysInstanced'
  9440. } else {
  9441. extension = extensions.get('ANGLE_instanced_arrays')
  9442. methodName = 'drawArraysInstancedANGLE'
  9443. if (extension === null) {
  9444. console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.')
  9445. return
  9446. }
  9447. }
  9448. extension[methodName](mode, start, count, primcount)
  9449. info.update(count, mode, primcount)
  9450. }
  9451. //
  9452. this.setMode = setMode
  9453. this.render = render
  9454. this.renderInstances = renderInstances
  9455. }
  9456. function WebGLCapabilities(gl, extensions, parameters) {
  9457. let maxAnisotropy
  9458. function getMaxAnisotropy() {
  9459. if (maxAnisotropy !== undefined) return maxAnisotropy
  9460. if (extensions.has('EXT_texture_filter_anisotropic') === true) {
  9461. const extension = extensions.get('EXT_texture_filter_anisotropic')
  9462. maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT)
  9463. } else {
  9464. maxAnisotropy = 0
  9465. }
  9466. return maxAnisotropy
  9467. }
  9468. function getMaxPrecision(precision) {
  9469. if (precision === 'highp') {
  9470. if (gl.getShaderPrecisionFormat(35633, 36338).precision > 0 && gl.getShaderPrecisionFormat(35632, 36338).precision > 0) {
  9471. return 'highp'
  9472. }
  9473. precision = 'mediump'
  9474. }
  9475. if (precision === 'mediump') {
  9476. if (gl.getShaderPrecisionFormat(35633, 36337).precision > 0 && gl.getShaderPrecisionFormat(35632, 36337).precision > 0) {
  9477. return 'mediump'
  9478. }
  9479. }
  9480. return 'lowp'
  9481. }
  9482. const isWebGL2 =
  9483. (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) || (typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext)
  9484. let precision = parameters.precision !== undefined ? parameters.precision : 'highp'
  9485. const maxPrecision = getMaxPrecision(precision)
  9486. if (maxPrecision !== precision) {
  9487. console.warn('THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.')
  9488. precision = maxPrecision
  9489. }
  9490. const drawBuffers = isWebGL2 || extensions.has('WEBGL_draw_buffers')
  9491. const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true
  9492. const maxTextures = gl.getParameter(34930)
  9493. const maxVertexTextures = gl.getParameter(35660)
  9494. const maxTextureSize = gl.getParameter(3379)
  9495. const maxCubemapSize = gl.getParameter(34076)
  9496. const maxAttributes = gl.getParameter(34921)
  9497. const maxVertexUniforms = gl.getParameter(36347)
  9498. const maxVaryings = gl.getParameter(36348)
  9499. const maxFragmentUniforms = gl.getParameter(36349)
  9500. const vertexTextures = maxVertexTextures > 0
  9501. const floatFragmentTextures = isWebGL2 || extensions.has('OES_texture_float')
  9502. const floatVertexTextures = vertexTextures && floatFragmentTextures
  9503. const maxSamples = isWebGL2 ? gl.getParameter(36183) : 0
  9504. return {
  9505. isWebGL2: isWebGL2,
  9506. drawBuffers: drawBuffers,
  9507. getMaxAnisotropy: getMaxAnisotropy,
  9508. getMaxPrecision: getMaxPrecision,
  9509. precision: precision,
  9510. logarithmicDepthBuffer: logarithmicDepthBuffer,
  9511. maxTextures: maxTextures,
  9512. maxVertexTextures: maxVertexTextures,
  9513. maxTextureSize: maxTextureSize,
  9514. maxCubemapSize: maxCubemapSize,
  9515. maxAttributes: maxAttributes,
  9516. maxVertexUniforms: maxVertexUniforms,
  9517. maxVaryings: maxVaryings,
  9518. maxFragmentUniforms: maxFragmentUniforms,
  9519. vertexTextures: vertexTextures,
  9520. floatFragmentTextures: floatFragmentTextures,
  9521. floatVertexTextures: floatVertexTextures,
  9522. maxSamples: maxSamples
  9523. }
  9524. }
  9525. function WebGLClipping(properties) {
  9526. const scope = this
  9527. let globalState = null,
  9528. numGlobalPlanes = 0,
  9529. localClippingEnabled = false,
  9530. renderingShadows = false
  9531. const plane = new Plane(),
  9532. viewNormalMatrix = new Matrix3(),
  9533. uniform = { value: null, needsUpdate: false }
  9534. this.uniform = uniform
  9535. this.numPlanes = 0
  9536. this.numIntersection = 0
  9537. this.init = function(planes, enableLocalClipping, camera) {
  9538. const enabled =
  9539. planes.length !== 0 ||
  9540. enableLocalClipping ||
  9541. // enable state of previous frame - the clipping code has to
  9542. // run another frame in order to reset the state:
  9543. numGlobalPlanes !== 0 ||
  9544. localClippingEnabled
  9545. localClippingEnabled = enableLocalClipping
  9546. globalState = projectPlanes(planes, camera, 0)
  9547. numGlobalPlanes = planes.length
  9548. return enabled
  9549. }
  9550. this.beginShadows = function() {
  9551. renderingShadows = true
  9552. projectPlanes(null)
  9553. }
  9554. this.endShadows = function() {
  9555. renderingShadows = false
  9556. resetGlobalState()
  9557. }
  9558. this.setState = function(material, camera, useCache) {
  9559. const planes = material.clippingPlanes,
  9560. clipIntersection = material.clipIntersection,
  9561. clipShadows = material.clipShadows
  9562. const materialProperties = properties.get(material)
  9563. if (!localClippingEnabled || planes === null || planes.length === 0 || (renderingShadows && !clipShadows)) {
  9564. // there's no local clipping
  9565. if (renderingShadows) {
  9566. // there's no global clipping
  9567. projectPlanes(null)
  9568. } else {
  9569. resetGlobalState()
  9570. }
  9571. } else {
  9572. const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
  9573. lGlobal = nGlobal * 4
  9574. let dstArray = materialProperties.clippingState || null
  9575. uniform.value = dstArray // ensure unique state
  9576. dstArray = projectPlanes(planes, camera, lGlobal, useCache)
  9577. for (let i = 0; i !== lGlobal; ++i) {
  9578. dstArray[i] = globalState[i]
  9579. }
  9580. materialProperties.clippingState = dstArray
  9581. this.numIntersection = clipIntersection ? this.numPlanes : 0
  9582. this.numPlanes += nGlobal
  9583. }
  9584. }
  9585. function resetGlobalState() {
  9586. if (uniform.value !== globalState) {
  9587. uniform.value = globalState
  9588. uniform.needsUpdate = numGlobalPlanes > 0
  9589. }
  9590. scope.numPlanes = numGlobalPlanes
  9591. scope.numIntersection = 0
  9592. }
  9593. function projectPlanes(planes, camera, dstOffset, skipTransform) {
  9594. const nPlanes = planes !== null ? planes.length : 0
  9595. let dstArray = null
  9596. if (nPlanes !== 0) {
  9597. dstArray = uniform.value
  9598. if (skipTransform !== true || dstArray === null) {
  9599. const flatSize = dstOffset + nPlanes * 4,
  9600. viewMatrix = camera.matrixWorldInverse
  9601. viewNormalMatrix.getNormalMatrix(viewMatrix)
  9602. if (dstArray === null || dstArray.length < flatSize) {
  9603. dstArray = new Float32Array(flatSize)
  9604. }
  9605. for (let i = 0, i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) {
  9606. plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix)
  9607. plane.normal.toArray(dstArray, i4)
  9608. dstArray[i4 + 3] = plane.constant
  9609. }
  9610. }
  9611. uniform.value = dstArray
  9612. uniform.needsUpdate = true
  9613. }
  9614. scope.numPlanes = nPlanes
  9615. scope.numIntersection = 0
  9616. return dstArray
  9617. }
  9618. }
  9619. function WebGLCubeMaps(renderer) {
  9620. let cubemaps = new WeakMap()
  9621. function mapTextureMapping(texture, mapping) {
  9622. if (mapping === EquirectangularReflectionMapping) {
  9623. texture.mapping = CubeReflectionMapping
  9624. } else if (mapping === EquirectangularRefractionMapping) {
  9625. texture.mapping = CubeRefractionMapping
  9626. }
  9627. return texture
  9628. }
  9629. function get(texture) {
  9630. if (texture && texture.isTexture && texture.isRenderTargetTexture === false) {
  9631. const mapping = texture.mapping
  9632. if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) {
  9633. if (cubemaps.has(texture)) {
  9634. const cubemap = cubemaps.get(texture).texture
  9635. return mapTextureMapping(cubemap, texture.mapping)
  9636. } else {
  9637. const image = texture.image
  9638. if (image && image.height > 0) {
  9639. const renderTarget = new WebGLCubeRenderTarget(image.height / 2)
  9640. renderTarget.fromEquirectangularTexture(renderer, texture)
  9641. cubemaps.set(texture, renderTarget)
  9642. texture.addEventListener('dispose', onTextureDispose)
  9643. return mapTextureMapping(renderTarget.texture, texture.mapping)
  9644. } else {
  9645. // image not yet ready. try the conversion next frame
  9646. return null
  9647. }
  9648. }
  9649. }
  9650. }
  9651. return texture
  9652. }
  9653. function onTextureDispose(event) {
  9654. const texture = event.target
  9655. texture.removeEventListener('dispose', onTextureDispose)
  9656. const cubemap = cubemaps.get(texture)
  9657. if (cubemap !== undefined) {
  9658. cubemaps.delete(texture)
  9659. cubemap.dispose()
  9660. }
  9661. }
  9662. function dispose() {
  9663. cubemaps = new WeakMap()
  9664. }
  9665. return {
  9666. get: get,
  9667. dispose: dispose
  9668. }
  9669. }
  9670. class OrthographicCamera extends Camera {
  9671. constructor(left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000) {
  9672. super()
  9673. this.isOrthographicCamera = true
  9674. this.type = 'OrthographicCamera'
  9675. this.zoom = 1
  9676. this.view = null
  9677. this.left = left
  9678. this.right = right
  9679. this.top = top
  9680. this.bottom = bottom
  9681. this.near = near
  9682. this.far = far
  9683. this.updateProjectionMatrix()
  9684. }
  9685. copy(source, recursive) {
  9686. super.copy(source, recursive)
  9687. this.left = source.left
  9688. this.right = source.right
  9689. this.top = source.top
  9690. this.bottom = source.bottom
  9691. this.near = source.near
  9692. this.far = source.far
  9693. this.zoom = source.zoom
  9694. this.view = source.view === null ? null : Object.assign({}, source.view)
  9695. return this
  9696. }
  9697. setViewOffset(fullWidth, fullHeight, x, y, width, height) {
  9698. if (this.view === null) {
  9699. this.view = {
  9700. enabled: true,
  9701. fullWidth: 1,
  9702. fullHeight: 1,
  9703. offsetX: 0,
  9704. offsetY: 0,
  9705. width: 1,
  9706. height: 1
  9707. }
  9708. }
  9709. this.view.enabled = true
  9710. this.view.fullWidth = fullWidth
  9711. this.view.fullHeight = fullHeight
  9712. this.view.offsetX = x
  9713. this.view.offsetY = y
  9714. this.view.width = width
  9715. this.view.height = height
  9716. this.updateProjectionMatrix()
  9717. }
  9718. clearViewOffset() {
  9719. if (this.view !== null) {
  9720. this.view.enabled = false
  9721. }
  9722. this.updateProjectionMatrix()
  9723. }
  9724. updateProjectionMatrix() {
  9725. const dx = (this.right - this.left) / (2 * this.zoom)
  9726. const dy = (this.top - this.bottom) / (2 * this.zoom)
  9727. const cx = (this.right + this.left) / 2
  9728. const cy = (this.top + this.bottom) / 2
  9729. let left = cx - dx
  9730. let right = cx + dx
  9731. let top = cy + dy
  9732. let bottom = cy - dy
  9733. if (this.view !== null && this.view.enabled) {
  9734. const scaleW = (this.right - this.left) / this.view.fullWidth / this.zoom
  9735. const scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom
  9736. left += scaleW * this.view.offsetX
  9737. right = left + scaleW * this.view.width
  9738. top -= scaleH * this.view.offsetY
  9739. bottom = top - scaleH * this.view.height
  9740. }
  9741. this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far)
  9742. this.projectionMatrixInverse.copy(this.projectionMatrix).invert()
  9743. }
  9744. toJSON(meta) {
  9745. const data = super.toJSON(meta)
  9746. data.object.zoom = this.zoom
  9747. data.object.left = this.left
  9748. data.object.right = this.right
  9749. data.object.top = this.top
  9750. data.object.bottom = this.bottom
  9751. data.object.near = this.near
  9752. data.object.far = this.far
  9753. if (this.view !== null) data.object.view = Object.assign({}, this.view)
  9754. return data
  9755. }
  9756. }
  9757. const LOD_MIN = 4
  9758. // The standard deviations (radians) associated with the extra mips. These are
  9759. // chosen to approximate a Trowbridge-Reitz distribution function times the
  9760. // geometric shadowing function. These sigma values squared must match the
  9761. // variance #defines in cube_uv_reflection_fragment.glsl.js.
  9762. const EXTRA_LOD_SIGMA = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582]
  9763. // The maximum length of the blur for loop. Smaller sigmas will use fewer
  9764. // samples and exit early, but not recompile the shader.
  9765. const MAX_SAMPLES = 20
  9766. const _flatCamera = /*@__PURE__*/ new OrthographicCamera()
  9767. const _clearColor = /*@__PURE__*/ new Color()
  9768. let _oldTarget = null
  9769. // Golden Ratio
  9770. const PHI = (1 + Math.sqrt(5)) / 2
  9771. const INV_PHI = 1 / PHI
  9772. // Vertices of a dodecahedron (except the opposites, which represent the
  9773. // same axis), used as axis directions evenly spread on a sphere.
  9774. const _axisDirections = [
  9775. /*@__PURE__*/ new Vector3(1, 1, 1),
  9776. /*@__PURE__*/ new Vector3(-1, 1, 1),
  9777. /*@__PURE__*/ new Vector3(1, 1, -1),
  9778. /*@__PURE__*/ new Vector3(-1, 1, -1),
  9779. /*@__PURE__*/ new Vector3(0, PHI, INV_PHI),
  9780. /*@__PURE__*/ new Vector3(0, PHI, -INV_PHI),
  9781. /*@__PURE__*/ new Vector3(INV_PHI, 0, PHI),
  9782. /*@__PURE__*/ new Vector3(-INV_PHI, 0, PHI),
  9783. /*@__PURE__*/ new Vector3(PHI, INV_PHI, 0),
  9784. /*@__PURE__*/ new Vector3(-PHI, INV_PHI, 0)
  9785. ]
  9786. /**
  9787. * This class generates a Prefiltered, Mipmapped Radiance Environment Map
  9788. * (PMREM) from a cubeMap environment texture. This allows different levels of
  9789. * blur to be quickly accessed based on material roughness. It is packed into a
  9790. * special CubeUV format that allows us to perform custom interpolation so that
  9791. * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
  9792. * chain, it only goes down to the LOD_MIN level (above), and then creates extra
  9793. * even more filtered 'mips' at the same LOD_MIN resolution, associated with
  9794. * higher roughness levels. In this way we maintain resolution to smoothly
  9795. * interpolate diffuse lighting while limiting sampling computation.
  9796. *
  9797. * Paper: Fast, Accurate Image-Based Lighting
  9798. * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
  9799. */
  9800. class PMREMGenerator {
  9801. constructor(renderer) {
  9802. this._renderer = renderer
  9803. this._pingPongRenderTarget = null
  9804. this._lodMax = 0
  9805. this._cubeSize = 0
  9806. this._lodPlanes = []
  9807. this._sizeLods = []
  9808. this._sigmas = []
  9809. this._blurMaterial = null
  9810. this._cubemapMaterial = null
  9811. this._equirectMaterial = null
  9812. this._compileMaterial(this._blurMaterial)
  9813. }
  9814. /**
  9815. * Generates a PMREM from a supplied Scene, which can be faster than using an
  9816. * image if networking bandwidth is low. Optional sigma specifies a blur radius
  9817. * in radians to be applied to the scene before PMREM generation. Optional near
  9818. * and far planes ensure the scene is rendered in its entirety (the cubeCamera
  9819. * is placed at the origin).
  9820. */
  9821. fromScene(scene, sigma = 0, near = 0.1, far = 100) {
  9822. _oldTarget = this._renderer.getRenderTarget()
  9823. this._setSize(256)
  9824. const cubeUVRenderTarget = this._allocateTargets()
  9825. cubeUVRenderTarget.depthBuffer = true
  9826. this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget)
  9827. if (sigma > 0) {
  9828. this._blur(cubeUVRenderTarget, 0, 0, sigma)
  9829. }
  9830. this._applyPMREM(cubeUVRenderTarget)
  9831. this._cleanup(cubeUVRenderTarget)
  9832. return cubeUVRenderTarget
  9833. }
  9834. /**
  9835. * Generates a PMREM from an equirectangular texture, which can be either LDR
  9836. * or HDR. The ideal input image size is 1k (1024 x 512),
  9837. * as this matches best with the 256 x 256 cubemap output.
  9838. */
  9839. fromEquirectangular(equirectangular, renderTarget = null) {
  9840. return this._fromTexture(equirectangular, renderTarget)
  9841. }
  9842. /**
  9843. * Generates a PMREM from an cubemap texture, which can be either LDR
  9844. * or HDR. The ideal input cube size is 256 x 256,
  9845. * as this matches best with the 256 x 256 cubemap output.
  9846. */
  9847. fromCubemap(cubemap, renderTarget = null) {
  9848. return this._fromTexture(cubemap, renderTarget)
  9849. }
  9850. /**
  9851. * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
  9852. * your texture's network fetch for increased concurrency.
  9853. */
  9854. compileCubemapShader() {
  9855. if (this._cubemapMaterial === null) {
  9856. this._cubemapMaterial = _getCubemapMaterial()
  9857. this._compileMaterial(this._cubemapMaterial)
  9858. }
  9859. }
  9860. /**
  9861. * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
  9862. * your texture's network fetch for increased concurrency.
  9863. */
  9864. compileEquirectangularShader() {
  9865. if (this._equirectMaterial === null) {
  9866. this._equirectMaterial = _getEquirectMaterial()
  9867. this._compileMaterial(this._equirectMaterial)
  9868. }
  9869. }
  9870. /**
  9871. * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
  9872. * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
  9873. * one of them will cause any others to also become unusable.
  9874. */
  9875. dispose() {
  9876. this._dispose()
  9877. if (this._cubemapMaterial !== null) this._cubemapMaterial.dispose()
  9878. if (this._equirectMaterial !== null) this._equirectMaterial.dispose()
  9879. }
  9880. // private interface
  9881. _setSize(cubeSize) {
  9882. this._lodMax = Math.floor(Math.log2(cubeSize))
  9883. this._cubeSize = Math.pow(2, this._lodMax)
  9884. }
  9885. _dispose() {
  9886. if (this._blurMaterial !== null) this._blurMaterial.dispose()
  9887. if (this._pingPongRenderTarget !== null) this._pingPongRenderTarget.dispose()
  9888. for (let i = 0; i < this._lodPlanes.length; i++) {
  9889. this._lodPlanes[i].dispose()
  9890. }
  9891. }
  9892. _cleanup(outputTarget) {
  9893. this._renderer.setRenderTarget(_oldTarget)
  9894. outputTarget.scissorTest = false
  9895. _setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height)
  9896. }
  9897. _fromTexture(texture, renderTarget) {
  9898. if (texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping) {
  9899. this._setSize(texture.image.length === 0 ? 16 : texture.image[0].width || texture.image[0].image.width)
  9900. } else {
  9901. // Equirectangular
  9902. this._setSize(texture.image.width / 4)
  9903. }
  9904. _oldTarget = this._renderer.getRenderTarget()
  9905. const cubeUVRenderTarget = renderTarget || this._allocateTargets()
  9906. this._textureToCubeUV(texture, cubeUVRenderTarget)
  9907. this._applyPMREM(cubeUVRenderTarget)
  9908. this._cleanup(cubeUVRenderTarget)
  9909. return cubeUVRenderTarget
  9910. }
  9911. _allocateTargets() {
  9912. const width = 3 * Math.max(this._cubeSize, 16 * 7)
  9913. const height = 4 * this._cubeSize
  9914. const params = {
  9915. magFilter: LinearFilter,
  9916. minFilter: LinearFilter,
  9917. generateMipmaps: false,
  9918. type: HalfFloatType,
  9919. format: RGBAFormat,
  9920. encoding: LinearEncoding,
  9921. depthBuffer: false
  9922. }
  9923. const cubeUVRenderTarget = _createRenderTarget(width, height, params)
  9924. if (this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width) {
  9925. if (this._pingPongRenderTarget !== null) {
  9926. this._dispose()
  9927. }
  9928. this._pingPongRenderTarget = _createRenderTarget(width, height, params)
  9929. const { _lodMax } = this
  9930. ;({ sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes(_lodMax))
  9931. this._blurMaterial = _getBlurShader(_lodMax, width, height)
  9932. }
  9933. return cubeUVRenderTarget
  9934. }
  9935. _compileMaterial(material) {
  9936. const tmpMesh = new Mesh(this._lodPlanes[0], material)
  9937. this._renderer.compile(tmpMesh, _flatCamera)
  9938. }
  9939. _sceneToCubeUV(scene, near, far, cubeUVRenderTarget) {
  9940. const fov = 90
  9941. const aspect = 1
  9942. const cubeCamera = new PerspectiveCamera(fov, aspect, near, far)
  9943. const upSign = [1, -1, 1, 1, 1, 1]
  9944. const forwardSign = [1, 1, 1, -1, -1, -1]
  9945. const renderer = this._renderer
  9946. const originalAutoClear = renderer.autoClear
  9947. const toneMapping = renderer.toneMapping
  9948. renderer.getClearColor(_clearColor)
  9949. renderer.toneMapping = NoToneMapping
  9950. renderer.autoClear = false
  9951. const backgroundMaterial = new MeshBasicMaterial({
  9952. name: 'PMREM.Background',
  9953. side: BackSide,
  9954. depthWrite: false,
  9955. depthTest: false
  9956. })
  9957. const backgroundBox = new Mesh(new BoxGeometry(), backgroundMaterial)
  9958. let useSolidColor = false
  9959. const background = scene.background
  9960. if (background) {
  9961. if (background.isColor) {
  9962. backgroundMaterial.color.copy(background)
  9963. scene.background = null
  9964. useSolidColor = true
  9965. }
  9966. } else {
  9967. backgroundMaterial.color.copy(_clearColor)
  9968. useSolidColor = true
  9969. }
  9970. for (let i = 0; i < 6; i++) {
  9971. const col = i % 3
  9972. if (col === 0) {
  9973. cubeCamera.up.set(0, upSign[i], 0)
  9974. cubeCamera.lookAt(forwardSign[i], 0, 0)
  9975. } else if (col === 1) {
  9976. cubeCamera.up.set(0, 0, upSign[i])
  9977. cubeCamera.lookAt(0, forwardSign[i], 0)
  9978. } else {
  9979. cubeCamera.up.set(0, upSign[i], 0)
  9980. cubeCamera.lookAt(0, 0, forwardSign[i])
  9981. }
  9982. const size = this._cubeSize
  9983. _setViewport(cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size)
  9984. renderer.setRenderTarget(cubeUVRenderTarget)
  9985. if (useSolidColor) {
  9986. renderer.render(backgroundBox, cubeCamera)
  9987. }
  9988. renderer.render(scene, cubeCamera)
  9989. }
  9990. backgroundBox.geometry.dispose()
  9991. backgroundBox.material.dispose()
  9992. renderer.toneMapping = toneMapping
  9993. renderer.autoClear = originalAutoClear
  9994. scene.background = background
  9995. }
  9996. _textureToCubeUV(texture, cubeUVRenderTarget) {
  9997. const renderer = this._renderer
  9998. const isCubeTexture = texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping
  9999. if (isCubeTexture) {
  10000. if (this._cubemapMaterial === null) {
  10001. this._cubemapMaterial = _getCubemapMaterial()
  10002. }
  10003. this._cubemapMaterial.uniforms.flipEnvMap.value = texture.isRenderTargetTexture === false ? -1 : 1
  10004. } else {
  10005. if (this._equirectMaterial === null) {
  10006. this._equirectMaterial = _getEquirectMaterial()
  10007. }
  10008. }
  10009. const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial
  10010. const mesh = new Mesh(this._lodPlanes[0], material)
  10011. const uniforms = material.uniforms
  10012. uniforms['envMap'].value = texture
  10013. const size = this._cubeSize
  10014. _setViewport(cubeUVRenderTarget, 0, 0, 3 * size, 2 * size)
  10015. renderer.setRenderTarget(cubeUVRenderTarget)
  10016. renderer.render(mesh, _flatCamera)
  10017. }
  10018. _applyPMREM(cubeUVRenderTarget) {
  10019. const renderer = this._renderer
  10020. const autoClear = renderer.autoClear
  10021. renderer.autoClear = false
  10022. for (let i = 1; i < this._lodPlanes.length; i++) {
  10023. const sigma = Math.sqrt(this._sigmas[i] * this._sigmas[i] - this._sigmas[i - 1] * this._sigmas[i - 1])
  10024. const poleAxis = _axisDirections[(i - 1) % _axisDirections.length]
  10025. this._blur(cubeUVRenderTarget, i - 1, i, sigma, poleAxis)
  10026. }
  10027. renderer.autoClear = autoClear
  10028. }
  10029. /**
  10030. * This is a two-pass Gaussian blur for a cubemap. Normally this is done
  10031. * vertically and horizontally, but this breaks down on a cube. Here we apply
  10032. * the blur latitudinally (around the poles), and then longitudinally (towards
  10033. * the poles) to approximate the orthogonally-separable blur. It is least
  10034. * accurate at the poles, but still does a decent job.
  10035. */
  10036. _blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) {
  10037. const pingPongRenderTarget = this._pingPongRenderTarget
  10038. this._halfBlur(cubeUVRenderTarget, pingPongRenderTarget, lodIn, lodOut, sigma, 'latitudinal', poleAxis)
  10039. this._halfBlur(pingPongRenderTarget, cubeUVRenderTarget, lodOut, lodOut, sigma, 'longitudinal', poleAxis)
  10040. }
  10041. _halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) {
  10042. const renderer = this._renderer
  10043. const blurMaterial = this._blurMaterial
  10044. if (direction !== 'latitudinal' && direction !== 'longitudinal') {
  10045. console.error('blur direction must be either latitudinal or longitudinal!')
  10046. }
  10047. // Number of standard deviations at which to cut off the discrete approximation.
  10048. const STANDARD_DEVIATIONS = 3
  10049. const blurMesh = new Mesh(this._lodPlanes[lodOut], blurMaterial)
  10050. const blurUniforms = blurMaterial.uniforms
  10051. const pixels = this._sizeLods[lodIn] - 1
  10052. const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : (2 * Math.PI) / (2 * MAX_SAMPLES - 1)
  10053. const sigmaPixels = sigmaRadians / radiansPerPixel
  10054. const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES
  10055. if (samples > MAX_SAMPLES) {
  10056. console.warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES}`)
  10057. }
  10058. const weights = []
  10059. let sum = 0
  10060. for (let i = 0; i < MAX_SAMPLES; ++i) {
  10061. const x = i / sigmaPixels
  10062. const weight = Math.exp((-x * x) / 2)
  10063. weights.push(weight)
  10064. if (i === 0) {
  10065. sum += weight
  10066. } else if (i < samples) {
  10067. sum += 2 * weight
  10068. }
  10069. }
  10070. for (let i = 0; i < weights.length; i++) {
  10071. weights[i] = weights[i] / sum
  10072. }
  10073. blurUniforms['envMap'].value = targetIn.texture
  10074. blurUniforms['samples'].value = samples
  10075. blurUniforms['weights'].value = weights
  10076. blurUniforms['latitudinal'].value = direction === 'latitudinal'
  10077. if (poleAxis) {
  10078. blurUniforms['poleAxis'].value = poleAxis
  10079. }
  10080. const { _lodMax } = this
  10081. blurUniforms['dTheta'].value = radiansPerPixel
  10082. blurUniforms['mipInt'].value = _lodMax - lodIn
  10083. const outputSize = this._sizeLods[lodOut]
  10084. const x = 3 * outputSize * (lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0)
  10085. const y = 4 * (this._cubeSize - outputSize)
  10086. _setViewport(targetOut, x, y, 3 * outputSize, 2 * outputSize)
  10087. renderer.setRenderTarget(targetOut)
  10088. renderer.render(blurMesh, _flatCamera)
  10089. }
  10090. }
  10091. function _createPlanes(lodMax) {
  10092. const lodPlanes = []
  10093. const sizeLods = []
  10094. const sigmas = []
  10095. let lod = lodMax
  10096. const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length
  10097. for (let i = 0; i < totalLods; i++) {
  10098. const sizeLod = Math.pow(2, lod)
  10099. sizeLods.push(sizeLod)
  10100. let sigma = 1.0 / sizeLod
  10101. if (i > lodMax - LOD_MIN) {
  10102. sigma = EXTRA_LOD_SIGMA[i - lodMax + LOD_MIN - 1]
  10103. } else if (i === 0) {
  10104. sigma = 0
  10105. }
  10106. sigmas.push(sigma)
  10107. const texelSize = 1.0 / (sizeLod - 2)
  10108. const min = -texelSize
  10109. const max = 1 + texelSize
  10110. const uv1 = [min, min, max, min, max, max, min, min, max, max, min, max]
  10111. const cubeFaces = 6
  10112. const vertices = 6
  10113. const positionSize = 3
  10114. const uvSize = 2
  10115. const faceIndexSize = 1
  10116. const position = new Float32Array(positionSize * vertices * cubeFaces)
  10117. const uv = new Float32Array(uvSize * vertices * cubeFaces)
  10118. const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces)
  10119. for (let face = 0; face < cubeFaces; face++) {
  10120. const x = ((face % 3) * 2) / 3 - 1
  10121. const y = face > 2 ? 0 : -1
  10122. const coordinates = [x, y, 0, x + 2 / 3, y, 0, x + 2 / 3, y + 1, 0, x, y, 0, x + 2 / 3, y + 1, 0, x, y + 1, 0]
  10123. position.set(coordinates, positionSize * vertices * face)
  10124. uv.set(uv1, uvSize * vertices * face)
  10125. const fill = [face, face, face, face, face, face]
  10126. faceIndex.set(fill, faceIndexSize * vertices * face)
  10127. }
  10128. const planes = new BufferGeometry()
  10129. planes.setAttribute('position', new BufferAttribute(position, positionSize))
  10130. planes.setAttribute('uv', new BufferAttribute(uv, uvSize))
  10131. planes.setAttribute('faceIndex', new BufferAttribute(faceIndex, faceIndexSize))
  10132. lodPlanes.push(planes)
  10133. if (lod > LOD_MIN) {
  10134. lod--
  10135. }
  10136. }
  10137. return { lodPlanes, sizeLods, sigmas }
  10138. }
  10139. function _createRenderTarget(width, height, params) {
  10140. const cubeUVRenderTarget = new WebGLRenderTarget(width, height, params)
  10141. cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping
  10142. cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'
  10143. cubeUVRenderTarget.scissorTest = true
  10144. return cubeUVRenderTarget
  10145. }
  10146. function _setViewport(target, x, y, width, height) {
  10147. target.viewport.set(x, y, width, height)
  10148. target.scissor.set(x, y, width, height)
  10149. }
  10150. function _getBlurShader(lodMax, width, height) {
  10151. const weights = new Float32Array(MAX_SAMPLES)
  10152. const poleAxis = new Vector3(0, 1, 0)
  10153. const shaderMaterial = new ShaderMaterial({
  10154. name: 'SphericalGaussianBlur',
  10155. defines: {
  10156. n: MAX_SAMPLES,
  10157. CUBEUV_TEXEL_WIDTH: 1.0 / width,
  10158. CUBEUV_TEXEL_HEIGHT: 1.0 / height,
  10159. CUBEUV_MAX_MIP: `${lodMax}.0`
  10160. },
  10161. uniforms: {
  10162. envMap: { value: null },
  10163. samples: { value: 1 },
  10164. weights: { value: weights },
  10165. latitudinal: { value: false },
  10166. dTheta: { value: 0 },
  10167. mipInt: { value: 0 },
  10168. poleAxis: { value: poleAxis }
  10169. },
  10170. vertexShader: _getCommonVertexShader(),
  10171. fragmentShader: /* glsl */ `
  10172. precision mediump float;
  10173. precision mediump int;
  10174. varying vec3 vOutputDirection;
  10175. uniform sampler2D envMap;
  10176. uniform int samples;
  10177. uniform float weights[ n ];
  10178. uniform bool latitudinal;
  10179. uniform float dTheta;
  10180. uniform float mipInt;
  10181. uniform vec3 poleAxis;
  10182. #define ENVMAP_TYPE_CUBE_UV
  10183. #include <cube_uv_reflection_fragment>
  10184. vec3 getSample( float theta, vec3 axis ) {
  10185. float cosTheta = cos( theta );
  10186. // Rodrigues' axis-angle rotation
  10187. vec3 sampleDirection = vOutputDirection * cosTheta
  10188. + cross( axis, vOutputDirection ) * sin( theta )
  10189. + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
  10190. return bilinearCubeUV( envMap, sampleDirection, mipInt );
  10191. }
  10192. void main() {
  10193. vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
  10194. if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
  10195. axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
  10196. }
  10197. axis = normalize( axis );
  10198. gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
  10199. gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
  10200. for ( int i = 1; i < n; i++ ) {
  10201. if ( i >= samples ) {
  10202. break;
  10203. }
  10204. float theta = dTheta * float( i );
  10205. gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
  10206. gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
  10207. }
  10208. }
  10209. `,
  10210. blending: NoBlending,
  10211. depthTest: false,
  10212. depthWrite: false
  10213. })
  10214. return shaderMaterial
  10215. }
  10216. function _getEquirectMaterial() {
  10217. return new ShaderMaterial({
  10218. name: 'EquirectangularToCubeUV',
  10219. uniforms: {
  10220. envMap: { value: null }
  10221. },
  10222. vertexShader: _getCommonVertexShader(),
  10223. fragmentShader: /* glsl */ `
  10224. precision mediump float;
  10225. precision mediump int;
  10226. varying vec3 vOutputDirection;
  10227. uniform sampler2D envMap;
  10228. #include <common>
  10229. void main() {
  10230. vec3 outputDirection = normalize( vOutputDirection );
  10231. vec2 uv = equirectUv( outputDirection );
  10232. gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
  10233. }
  10234. `,
  10235. blending: NoBlending,
  10236. depthTest: false,
  10237. depthWrite: false
  10238. })
  10239. }
  10240. function _getCubemapMaterial() {
  10241. return new ShaderMaterial({
  10242. name: 'CubemapToCubeUV',
  10243. uniforms: {
  10244. envMap: { value: null },
  10245. flipEnvMap: { value: -1 }
  10246. },
  10247. vertexShader: _getCommonVertexShader(),
  10248. fragmentShader: /* glsl */ `
  10249. precision mediump float;
  10250. precision mediump int;
  10251. uniform float flipEnvMap;
  10252. varying vec3 vOutputDirection;
  10253. uniform samplerCube envMap;
  10254. void main() {
  10255. gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
  10256. }
  10257. `,
  10258. blending: NoBlending,
  10259. depthTest: false,
  10260. depthWrite: false
  10261. })
  10262. }
  10263. function _getCommonVertexShader() {
  10264. return /* glsl */ `
  10265. precision mediump float;
  10266. precision mediump int;
  10267. attribute float faceIndex;
  10268. varying vec3 vOutputDirection;
  10269. // RH coordinate system; PMREM face-indexing convention
  10270. vec3 getDirection( vec2 uv, float face ) {
  10271. uv = 2.0 * uv - 1.0;
  10272. vec3 direction = vec3( uv, 1.0 );
  10273. if ( face == 0.0 ) {
  10274. direction = direction.zyx; // ( 1, v, u ) pos x
  10275. } else if ( face == 1.0 ) {
  10276. direction = direction.xzy;
  10277. direction.xz *= -1.0; // ( -u, 1, -v ) pos y
  10278. } else if ( face == 2.0 ) {
  10279. direction.x *= -1.0; // ( -u, v, 1 ) pos z
  10280. } else if ( face == 3.0 ) {
  10281. direction = direction.zyx;
  10282. direction.xz *= -1.0; // ( -1, v, -u ) neg x
  10283. } else if ( face == 4.0 ) {
  10284. direction = direction.xzy;
  10285. direction.xy *= -1.0; // ( -u, -1, v ) neg y
  10286. } else if ( face == 5.0 ) {
  10287. direction.z *= -1.0; // ( u, v, -1 ) neg z
  10288. }
  10289. return direction;
  10290. }
  10291. void main() {
  10292. vOutputDirection = getDirection( uv, faceIndex );
  10293. gl_Position = vec4( position, 1.0 );
  10294. }
  10295. `
  10296. }
  10297. function WebGLCubeUVMaps(renderer) {
  10298. let cubeUVmaps = new WeakMap()
  10299. let pmremGenerator = null
  10300. function get(texture) {
  10301. if (texture && texture.isTexture) {
  10302. const mapping = texture.mapping
  10303. const isEquirectMap = mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping
  10304. const isCubeMap = mapping === CubeReflectionMapping || mapping === CubeRefractionMapping
  10305. // equirect/cube map to cubeUV conversion
  10306. if (isEquirectMap || isCubeMap) {
  10307. if (texture.isRenderTargetTexture && texture.needsPMREMUpdate === true) {
  10308. texture.needsPMREMUpdate = false
  10309. let renderTarget = cubeUVmaps.get(texture)
  10310. if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer)
  10311. renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture, renderTarget)
  10312. cubeUVmaps.set(texture, renderTarget)
  10313. return renderTarget.texture
  10314. } else {
  10315. if (cubeUVmaps.has(texture)) {
  10316. return cubeUVmaps.get(texture).texture
  10317. } else {
  10318. const image = texture.image
  10319. if ((isEquirectMap && image && image.height > 0) || (isCubeMap && image && isCubeTextureComplete(image))) {
  10320. if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer)
  10321. const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture)
  10322. cubeUVmaps.set(texture, renderTarget)
  10323. texture.addEventListener('dispose', onTextureDispose)
  10324. return renderTarget.texture
  10325. } else {
  10326. // image not yet ready. try the conversion next frame
  10327. return null
  10328. }
  10329. }
  10330. }
  10331. }
  10332. }
  10333. return texture
  10334. }
  10335. function isCubeTextureComplete(image) {
  10336. let count = 0
  10337. const length = 6
  10338. for (let i = 0; i < length; i++) {
  10339. if (image[i] !== undefined) count++
  10340. }
  10341. return count === length
  10342. }
  10343. function onTextureDispose(event) {
  10344. const texture = event.target
  10345. texture.removeEventListener('dispose', onTextureDispose)
  10346. const cubemapUV = cubeUVmaps.get(texture)
  10347. if (cubemapUV !== undefined) {
  10348. cubeUVmaps.delete(texture)
  10349. cubemapUV.dispose()
  10350. }
  10351. }
  10352. function dispose() {
  10353. cubeUVmaps = new WeakMap()
  10354. if (pmremGenerator !== null) {
  10355. pmremGenerator.dispose()
  10356. pmremGenerator = null
  10357. }
  10358. }
  10359. return {
  10360. get: get,
  10361. dispose: dispose
  10362. }
  10363. }
  10364. function WebGLExtensions(gl) {
  10365. const extensions = {}
  10366. function getExtension(name) {
  10367. if (extensions[name] !== undefined) {
  10368. return extensions[name]
  10369. }
  10370. let extension
  10371. switch (name) {
  10372. case 'WEBGL_depth_texture':
  10373. extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture')
  10374. break
  10375. case 'EXT_texture_filter_anisotropic':
  10376. extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic')
  10377. break
  10378. case 'WEBGL_compressed_texture_s3tc':
  10379. extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc')
  10380. break
  10381. case 'WEBGL_compressed_texture_pvrtc':
  10382. extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc')
  10383. break
  10384. default:
  10385. extension = gl.getExtension(name)
  10386. }
  10387. extensions[name] = extension
  10388. return extension
  10389. }
  10390. return {
  10391. has: function(name) {
  10392. return getExtension(name) !== null
  10393. },
  10394. init: function(capabilities) {
  10395. if (capabilities.isWebGL2) {
  10396. getExtension('EXT_color_buffer_float')
  10397. } else {
  10398. getExtension('WEBGL_depth_texture')
  10399. getExtension('OES_texture_float')
  10400. getExtension('OES_texture_half_float')
  10401. getExtension('OES_texture_half_float_linear')
  10402. getExtension('OES_standard_derivatives')
  10403. getExtension('OES_element_index_uint')
  10404. getExtension('OES_vertex_array_object')
  10405. getExtension('ANGLE_instanced_arrays')
  10406. }
  10407. getExtension('OES_texture_float_linear')
  10408. getExtension('EXT_color_buffer_half_float')
  10409. getExtension('WEBGL_multisampled_render_to_texture')
  10410. },
  10411. get: function(name) {
  10412. const extension = getExtension(name)
  10413. if (extension === null) {
  10414. console.warn('THREE.WebGLRenderer: ' + name + ' extension not supported.')
  10415. }
  10416. return extension
  10417. }
  10418. }
  10419. }
  10420. function WebGLGeometries(gl, attributes, info, bindingStates) {
  10421. const geometries = {}
  10422. const wireframeAttributes = new WeakMap()
  10423. function onGeometryDispose(event) {
  10424. const geometry = event.target
  10425. if (geometry.index !== null) {
  10426. attributes.remove(geometry.index)
  10427. }
  10428. for (const name in geometry.attributes) {
  10429. attributes.remove(geometry.attributes[name])
  10430. }
  10431. geometry.removeEventListener('dispose', onGeometryDispose)
  10432. delete geometries[geometry.id]
  10433. const attribute = wireframeAttributes.get(geometry)
  10434. if (attribute) {
  10435. attributes.remove(attribute)
  10436. wireframeAttributes.delete(geometry)
  10437. }
  10438. bindingStates.releaseStatesOfGeometry(geometry)
  10439. if (geometry.isInstancedBufferGeometry === true) {
  10440. delete geometry._maxInstanceCount
  10441. }
  10442. //
  10443. info.memory.geometries--
  10444. }
  10445. function get(object, geometry) {
  10446. if (geometries[geometry.id] === true) return geometry
  10447. geometry.addEventListener('dispose', onGeometryDispose)
  10448. geometries[geometry.id] = true
  10449. info.memory.geometries++
  10450. return geometry
  10451. }
  10452. function update(geometry) {
  10453. const geometryAttributes = geometry.attributes
  10454. // Updating index buffer in VAO now. See WebGLBindingStates.
  10455. for (const name in geometryAttributes) {
  10456. attributes.update(geometryAttributes[name], 34962)
  10457. }
  10458. // morph targets
  10459. const morphAttributes = geometry.morphAttributes
  10460. for (const name in morphAttributes) {
  10461. const array = morphAttributes[name]
  10462. for (let i = 0, l = array.length; i < l; i++) {
  10463. attributes.update(array[i], 34962)
  10464. }
  10465. }
  10466. }
  10467. function updateWireframeAttribute(geometry) {
  10468. const indices = []
  10469. const geometryIndex = geometry.index
  10470. const geometryPosition = geometry.attributes.position
  10471. let version = 0
  10472. if (geometryIndex !== null) {
  10473. const array = geometryIndex.array
  10474. version = geometryIndex.version
  10475. for (let i = 0, l = array.length; i < l; i += 3) {
  10476. const a = array[i + 0]
  10477. const b = array[i + 1]
  10478. const c = array[i + 2]
  10479. indices.push(a, b, b, c, c, a)
  10480. }
  10481. } else {
  10482. const array = geometryPosition.array
  10483. version = geometryPosition.version
  10484. for (let i = 0, l = array.length / 3 - 1; i < l; i += 3) {
  10485. const a = i + 0
  10486. const b = i + 1
  10487. const c = i + 2
  10488. indices.push(a, b, b, c, c, a)
  10489. }
  10490. }
  10491. const attribute = new (arrayNeedsUint32(indices) ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1)
  10492. attribute.version = version
  10493. // Updating index buffer in VAO now. See WebGLBindingStates
  10494. //
  10495. const previousAttribute = wireframeAttributes.get(geometry)
  10496. if (previousAttribute) attributes.remove(previousAttribute)
  10497. //
  10498. wireframeAttributes.set(geometry, attribute)
  10499. }
  10500. function getWireframeAttribute(geometry) {
  10501. const currentAttribute = wireframeAttributes.get(geometry)
  10502. if (currentAttribute) {
  10503. const geometryIndex = geometry.index
  10504. if (geometryIndex !== null) {
  10505. // if the attribute is obsolete, create a new one
  10506. if (currentAttribute.version < geometryIndex.version) {
  10507. updateWireframeAttribute(geometry)
  10508. }
  10509. }
  10510. } else {
  10511. updateWireframeAttribute(geometry)
  10512. }
  10513. return wireframeAttributes.get(geometry)
  10514. }
  10515. return {
  10516. get: get,
  10517. update: update,
  10518. getWireframeAttribute: getWireframeAttribute
  10519. }
  10520. }
  10521. function WebGLIndexedBufferRenderer(gl, extensions, info, capabilities) {
  10522. const isWebGL2 = capabilities.isWebGL2
  10523. let mode
  10524. function setMode(value) {
  10525. mode = value
  10526. }
  10527. let type, bytesPerElement
  10528. function setIndex(value) {
  10529. type = value.type
  10530. bytesPerElement = value.bytesPerElement
  10531. }
  10532. function render(start, count) {
  10533. gl.drawElements(mode, count, type, start * bytesPerElement)
  10534. info.update(count, mode, 1)
  10535. }
  10536. function renderInstances(start, count, primcount) {
  10537. if (primcount === 0) return
  10538. let extension, methodName
  10539. if (isWebGL2) {
  10540. extension = gl
  10541. methodName = 'drawElementsInstanced'
  10542. } else {
  10543. extension = extensions.get('ANGLE_instanced_arrays')
  10544. methodName = 'drawElementsInstancedANGLE'
  10545. if (extension === null) {
  10546. console.error('THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.')
  10547. return
  10548. }
  10549. }
  10550. extension[methodName](mode, count, type, start * bytesPerElement, primcount)
  10551. info.update(count, mode, primcount)
  10552. }
  10553. //
  10554. this.setMode = setMode
  10555. this.setIndex = setIndex
  10556. this.render = render
  10557. this.renderInstances = renderInstances
  10558. }
  10559. function WebGLInfo(gl) {
  10560. const memory = {
  10561. geometries: 0,
  10562. textures: 0
  10563. }
  10564. const render = {
  10565. frame: 0,
  10566. calls: 0,
  10567. triangles: 0,
  10568. points: 0,
  10569. lines: 0
  10570. }
  10571. function update(count, mode, instanceCount) {
  10572. render.calls++
  10573. switch (mode) {
  10574. case 4:
  10575. render.triangles += instanceCount * (count / 3)
  10576. break
  10577. case 1:
  10578. render.lines += instanceCount * (count / 2)
  10579. break
  10580. case 3:
  10581. render.lines += instanceCount * (count - 1)
  10582. break
  10583. case 2:
  10584. render.lines += instanceCount * count
  10585. break
  10586. case 0:
  10587. render.points += instanceCount * count
  10588. break
  10589. default:
  10590. console.error('THREE.WebGLInfo: Unknown draw mode:', mode)
  10591. break
  10592. }
  10593. }
  10594. function reset() {
  10595. render.frame++
  10596. render.calls = 0
  10597. render.triangles = 0
  10598. render.points = 0
  10599. render.lines = 0
  10600. }
  10601. return {
  10602. memory: memory,
  10603. render: render,
  10604. programs: null,
  10605. autoReset: true,
  10606. reset: reset,
  10607. update: update
  10608. }
  10609. }
  10610. function numericalSort(a, b) {
  10611. return a[0] - b[0]
  10612. }
  10613. function absNumericalSort(a, b) {
  10614. return Math.abs(b[1]) - Math.abs(a[1])
  10615. }
  10616. function denormalize(morph, attribute) {
  10617. let denominator = 1
  10618. const array = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array
  10619. if (array instanceof Int8Array) denominator = 127
  10620. else if (array instanceof Int16Array) denominator = 32767
  10621. else if (array instanceof Int32Array) denominator = 2147483647
  10622. else console.error('THREE.WebGLMorphtargets: Unsupported morph attribute data type: ', array)
  10623. morph.divideScalar(denominator)
  10624. }
  10625. function WebGLMorphtargets(gl, capabilities, textures) {
  10626. const influencesList = {}
  10627. const morphInfluences = new Float32Array(8)
  10628. const morphTextures = new WeakMap()
  10629. const morph = new Vector4()
  10630. const workInfluences = []
  10631. for (let i = 0; i < 8; i++) {
  10632. workInfluences[i] = [i, 0]
  10633. }
  10634. function update(object, geometry, material, program) {
  10635. const objectInfluences = object.morphTargetInfluences
  10636. if (capabilities.isWebGL2 === true) {
  10637. // instead of using attributes, the WebGL 2 code path encodes morph targets
  10638. // into an array of data textures. Each layer represents a single morph target.
  10639. const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color
  10640. const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0
  10641. let entry = morphTextures.get(geometry)
  10642. if (entry === undefined || entry.count !== morphTargetsCount) {
  10643. if (entry !== undefined) entry.texture.dispose()
  10644. const hasMorphPosition = geometry.morphAttributes.position !== undefined
  10645. const hasMorphNormals = geometry.morphAttributes.normal !== undefined
  10646. const hasMorphColors = geometry.morphAttributes.color !== undefined
  10647. const morphTargets = geometry.morphAttributes.position || []
  10648. const morphNormals = geometry.morphAttributes.normal || []
  10649. const morphColors = geometry.morphAttributes.color || []
  10650. let vertexDataCount = 0
  10651. if (hasMorphPosition === true) vertexDataCount = 1
  10652. if (hasMorphNormals === true) vertexDataCount = 2
  10653. if (hasMorphColors === true) vertexDataCount = 3
  10654. let width = geometry.attributes.position.count * vertexDataCount
  10655. let height = 1
  10656. if (width > capabilities.maxTextureSize) {
  10657. height = Math.ceil(width / capabilities.maxTextureSize)
  10658. width = capabilities.maxTextureSize
  10659. }
  10660. const buffer = new Float32Array(width * height * 4 * morphTargetsCount)
  10661. const texture = new DataArrayTexture(buffer, width, height, morphTargetsCount)
  10662. texture.type = FloatType
  10663. texture.needsUpdate = true
  10664. // fill buffer
  10665. const vertexDataStride = vertexDataCount * 4
  10666. for (let i = 0; i < morphTargetsCount; i++) {
  10667. const morphTarget = morphTargets[i]
  10668. const morphNormal = morphNormals[i]
  10669. const morphColor = morphColors[i]
  10670. const offset = width * height * 4 * i
  10671. for (let j = 0; j < morphTarget.count; j++) {
  10672. const stride = j * vertexDataStride
  10673. if (hasMorphPosition === true) {
  10674. morph.fromBufferAttribute(morphTarget, j)
  10675. if (morphTarget.normalized === true) denormalize(morph, morphTarget)
  10676. buffer[offset + stride + 0] = morph.x
  10677. buffer[offset + stride + 1] = morph.y
  10678. buffer[offset + stride + 2] = morph.z
  10679. buffer[offset + stride + 3] = 0
  10680. }
  10681. if (hasMorphNormals === true) {
  10682. morph.fromBufferAttribute(morphNormal, j)
  10683. if (morphNormal.normalized === true) denormalize(morph, morphNormal)
  10684. buffer[offset + stride + 4] = morph.x
  10685. buffer[offset + stride + 5] = morph.y
  10686. buffer[offset + stride + 6] = morph.z
  10687. buffer[offset + stride + 7] = 0
  10688. }
  10689. if (hasMorphColors === true) {
  10690. morph.fromBufferAttribute(morphColor, j)
  10691. if (morphColor.normalized === true) denormalize(morph, morphColor)
  10692. buffer[offset + stride + 8] = morph.x
  10693. buffer[offset + stride + 9] = morph.y
  10694. buffer[offset + stride + 10] = morph.z
  10695. buffer[offset + stride + 11] = morphColor.itemSize === 4 ? morph.w : 1
  10696. }
  10697. }
  10698. }
  10699. entry = {
  10700. count: morphTargetsCount,
  10701. texture: texture,
  10702. size: new Vector2(width, height)
  10703. }
  10704. morphTextures.set(geometry, entry)
  10705. function disposeTexture() {
  10706. texture.dispose()
  10707. morphTextures.delete(geometry)
  10708. geometry.removeEventListener('dispose', disposeTexture)
  10709. }
  10710. geometry.addEventListener('dispose', disposeTexture)
  10711. }
  10712. //
  10713. let morphInfluencesSum = 0
  10714. for (let i = 0; i < objectInfluences.length; i++) {
  10715. morphInfluencesSum += objectInfluences[i]
  10716. }
  10717. const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum
  10718. program.getUniforms().setValue(gl, 'morphTargetBaseInfluence', morphBaseInfluence)
  10719. program.getUniforms().setValue(gl, 'morphTargetInfluences', objectInfluences)
  10720. program.getUniforms().setValue(gl, 'morphTargetsTexture', entry.texture, textures)
  10721. program.getUniforms().setValue(gl, 'morphTargetsTextureSize', entry.size)
  10722. } else {
  10723. // When object doesn't have morph target influences defined, we treat it as a 0-length array
  10724. // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
  10725. const length = objectInfluences === undefined ? 0 : objectInfluences.length
  10726. let influences = influencesList[geometry.id]
  10727. if (influences === undefined || influences.length !== length) {
  10728. // initialise list
  10729. influences = []
  10730. for (let i = 0; i < length; i++) {
  10731. influences[i] = [i, 0]
  10732. }
  10733. influencesList[geometry.id] = influences
  10734. }
  10735. // Collect influences
  10736. for (let i = 0; i < length; i++) {
  10737. const influence = influences[i]
  10738. influence[0] = i
  10739. influence[1] = objectInfluences[i]
  10740. }
  10741. influences.sort(absNumericalSort)
  10742. for (let i = 0; i < 8; i++) {
  10743. if (i < length && influences[i][1]) {
  10744. workInfluences[i][0] = influences[i][0]
  10745. workInfluences[i][1] = influences[i][1]
  10746. } else {
  10747. workInfluences[i][0] = Number.MAX_SAFE_INTEGER
  10748. workInfluences[i][1] = 0
  10749. }
  10750. }
  10751. workInfluences.sort(numericalSort)
  10752. const morphTargets = geometry.morphAttributes.position
  10753. const morphNormals = geometry.morphAttributes.normal
  10754. let morphInfluencesSum = 0
  10755. for (let i = 0; i < 8; i++) {
  10756. const influence = workInfluences[i]
  10757. const index = influence[0]
  10758. const value = influence[1]
  10759. if (index !== Number.MAX_SAFE_INTEGER && value) {
  10760. if (morphTargets && geometry.getAttribute('morphTarget' + i) !== morphTargets[index]) {
  10761. geometry.setAttribute('morphTarget' + i, morphTargets[index])
  10762. }
  10763. if (morphNormals && geometry.getAttribute('morphNormal' + i) !== morphNormals[index]) {
  10764. geometry.setAttribute('morphNormal' + i, morphNormals[index])
  10765. }
  10766. morphInfluences[i] = value
  10767. morphInfluencesSum += value
  10768. } else {
  10769. if (morphTargets && geometry.hasAttribute('morphTarget' + i) === true) {
  10770. geometry.deleteAttribute('morphTarget' + i)
  10771. }
  10772. if (morphNormals && geometry.hasAttribute('morphNormal' + i) === true) {
  10773. geometry.deleteAttribute('morphNormal' + i)
  10774. }
  10775. morphInfluences[i] = 0
  10776. }
  10777. }
  10778. // GLSL shader uses formula baseinfluence * base + sum(target * influence)
  10779. // This allows us to switch between absolute morphs and relative morphs without changing shader code
  10780. // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
  10781. const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum
  10782. program.getUniforms().setValue(gl, 'morphTargetBaseInfluence', morphBaseInfluence)
  10783. program.getUniforms().setValue(gl, 'morphTargetInfluences', morphInfluences)
  10784. }
  10785. }
  10786. return {
  10787. update: update
  10788. }
  10789. }
  10790. function WebGLObjects(gl, geometries, attributes, info) {
  10791. let updateMap = new WeakMap()
  10792. function update(object) {
  10793. const frame = info.render.frame
  10794. const geometry = object.geometry
  10795. const buffergeometry = geometries.get(object, geometry)
  10796. // Update once per frame
  10797. if (updateMap.get(buffergeometry) !== frame) {
  10798. geometries.update(buffergeometry)
  10799. updateMap.set(buffergeometry, frame)
  10800. }
  10801. if (object.isInstancedMesh) {
  10802. if (object.hasEventListener('dispose', onInstancedMeshDispose) === false) {
  10803. object.addEventListener('dispose', onInstancedMeshDispose)
  10804. }
  10805. attributes.update(object.instanceMatrix, 34962)
  10806. if (object.instanceColor !== null) {
  10807. attributes.update(object.instanceColor, 34962)
  10808. }
  10809. }
  10810. return buffergeometry
  10811. }
  10812. function dispose() {
  10813. updateMap = new WeakMap()
  10814. }
  10815. function onInstancedMeshDispose(event) {
  10816. const instancedMesh = event.target
  10817. instancedMesh.removeEventListener('dispose', onInstancedMeshDispose)
  10818. attributes.remove(instancedMesh.instanceMatrix)
  10819. if (instancedMesh.instanceColor !== null) attributes.remove(instancedMesh.instanceColor)
  10820. }
  10821. return {
  10822. update: update,
  10823. dispose: dispose
  10824. }
  10825. }
  10826. /**
  10827. * Uniforms of a program.
  10828. * Those form a tree structure with a special top-level container for the root,
  10829. * which you get by calling 'new WebGLUniforms( gl, program )'.
  10830. *
  10831. *
  10832. * Properties of inner nodes including the top-level container:
  10833. *
  10834. * .seq - array of nested uniforms
  10835. * .map - nested uniforms by name
  10836. *
  10837. *
  10838. * Methods of all nodes except the top-level container:
  10839. *
  10840. * .setValue( gl, value, [textures] )
  10841. *
  10842. * uploads a uniform value(s)
  10843. * the 'textures' parameter is needed for sampler uniforms
  10844. *
  10845. *
  10846. * Static methods of the top-level container (textures factorizations):
  10847. *
  10848. * .upload( gl, seq, values, textures )
  10849. *
  10850. * sets uniforms in 'seq' to 'values[id].value'
  10851. *
  10852. * .seqWithValue( seq, values ) : filteredSeq
  10853. *
  10854. * filters 'seq' entries with corresponding entry in values
  10855. *
  10856. *
  10857. * Methods of the top-level container (textures factorizations):
  10858. *
  10859. * .setValue( gl, name, value, textures )
  10860. *
  10861. * sets uniform with name 'name' to 'value'
  10862. *
  10863. * .setOptional( gl, obj, prop )
  10864. *
  10865. * like .set for an optional property of the object
  10866. *
  10867. */
  10868. const emptyTexture = new Texture()
  10869. const emptyArrayTexture = new DataArrayTexture()
  10870. const empty3dTexture = new Data3DTexture()
  10871. const emptyCubeTexture = new CubeTexture()
  10872. // --- Utilities ---
  10873. // Array Caches (provide typed arrays for temporary by size)
  10874. const arrayCacheF32 = []
  10875. const arrayCacheI32 = []
  10876. // Float32Array caches used for uploading Matrix uniforms
  10877. const mat4array = new Float32Array(16)
  10878. const mat3array = new Float32Array(9)
  10879. const mat2array = new Float32Array(4)
  10880. // Flattening for arrays of vectors and matrices
  10881. function flatten(array, nBlocks, blockSize) {
  10882. const firstElem = array[0]
  10883. if (firstElem <= 0 || firstElem > 0) return array
  10884. // unoptimized: ! isNaN( firstElem )
  10885. // see http://jacksondunstan.com/articles/983
  10886. const n = nBlocks * blockSize
  10887. let r = arrayCacheF32[n]
  10888. if (r === undefined) {
  10889. r = new Float32Array(n)
  10890. arrayCacheF32[n] = r
  10891. }
  10892. if (nBlocks !== 0) {
  10893. firstElem.toArray(r, 0)
  10894. for (let i = 1, offset = 0; i !== nBlocks; ++i) {
  10895. offset += blockSize
  10896. array[i].toArray(r, offset)
  10897. }
  10898. }
  10899. return r
  10900. }
  10901. function arraysEqual(a, b) {
  10902. if (a.length !== b.length) return false
  10903. for (let i = 0, l = a.length; i < l; i++) {
  10904. if (a[i] !== b[i]) return false
  10905. }
  10906. return true
  10907. }
  10908. function copyArray(a, b) {
  10909. for (let i = 0, l = b.length; i < l; i++) {
  10910. a[i] = b[i]
  10911. }
  10912. }
  10913. // Texture unit allocation
  10914. function allocTexUnits(textures, n) {
  10915. let r = arrayCacheI32[n]
  10916. if (r === undefined) {
  10917. r = new Int32Array(n)
  10918. arrayCacheI32[n] = r
  10919. }
  10920. for (let i = 0; i !== n; ++i) {
  10921. r[i] = textures.allocateTextureUnit()
  10922. }
  10923. return r
  10924. }
  10925. // --- Setters ---
  10926. // Note: Defining these methods externally, because they come in a bunch
  10927. // and this way their names minify.
  10928. // Single scalar
  10929. function setValueV1f(gl, v) {
  10930. const cache = this.cache
  10931. if (cache[0] === v) return
  10932. gl.uniform1f(this.addr, v)
  10933. cache[0] = v
  10934. }
  10935. // Single float vector (from flat array or THREE.VectorN)
  10936. function setValueV2f(gl, v) {
  10937. const cache = this.cache
  10938. if (v.x !== undefined) {
  10939. if (cache[0] !== v.x || cache[1] !== v.y) {
  10940. gl.uniform2f(this.addr, v.x, v.y)
  10941. cache[0] = v.x
  10942. cache[1] = v.y
  10943. }
  10944. } else {
  10945. if (arraysEqual(cache, v)) return
  10946. gl.uniform2fv(this.addr, v)
  10947. copyArray(cache, v)
  10948. }
  10949. }
  10950. function setValueV3f(gl, v) {
  10951. const cache = this.cache
  10952. if (v.x !== undefined) {
  10953. if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) {
  10954. gl.uniform3f(this.addr, v.x, v.y, v.z)
  10955. cache[0] = v.x
  10956. cache[1] = v.y
  10957. cache[2] = v.z
  10958. }
  10959. } else if (v.r !== undefined) {
  10960. if (cache[0] !== v.r || cache[1] !== v.g || cache[2] !== v.b) {
  10961. gl.uniform3f(this.addr, v.r, v.g, v.b)
  10962. cache[0] = v.r
  10963. cache[1] = v.g
  10964. cache[2] = v.b
  10965. }
  10966. } else {
  10967. if (arraysEqual(cache, v)) return
  10968. gl.uniform3fv(this.addr, v)
  10969. copyArray(cache, v)
  10970. }
  10971. }
  10972. function setValueV4f(gl, v) {
  10973. const cache = this.cache
  10974. if (v.x !== undefined) {
  10975. if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z || cache[3] !== v.w) {
  10976. gl.uniform4f(this.addr, v.x, v.y, v.z, v.w)
  10977. cache[0] = v.x
  10978. cache[1] = v.y
  10979. cache[2] = v.z
  10980. cache[3] = v.w
  10981. }
  10982. } else {
  10983. if (arraysEqual(cache, v)) return
  10984. gl.uniform4fv(this.addr, v)
  10985. copyArray(cache, v)
  10986. }
  10987. }
  10988. // Single matrix (from flat array or THREE.MatrixN)
  10989. function setValueM2(gl, v) {
  10990. const cache = this.cache
  10991. const elements = v.elements
  10992. if (elements === undefined) {
  10993. if (arraysEqual(cache, v)) return
  10994. gl.uniformMatrix2fv(this.addr, false, v)
  10995. copyArray(cache, v)
  10996. } else {
  10997. if (arraysEqual(cache, elements)) return
  10998. mat2array.set(elements)
  10999. gl.uniformMatrix2fv(this.addr, false, mat2array)
  11000. copyArray(cache, elements)
  11001. }
  11002. }
  11003. function setValueM3(gl, v) {
  11004. const cache = this.cache
  11005. const elements = v.elements
  11006. if (elements === undefined) {
  11007. if (arraysEqual(cache, v)) return
  11008. gl.uniformMatrix3fv(this.addr, false, v)
  11009. copyArray(cache, v)
  11010. } else {
  11011. if (arraysEqual(cache, elements)) return
  11012. mat3array.set(elements)
  11013. gl.uniformMatrix3fv(this.addr, false, mat3array)
  11014. copyArray(cache, elements)
  11015. }
  11016. }
  11017. function setValueM4(gl, v) {
  11018. const cache = this.cache
  11019. const elements = v.elements
  11020. if (elements === undefined) {
  11021. if (arraysEqual(cache, v)) return
  11022. gl.uniformMatrix4fv(this.addr, false, v)
  11023. copyArray(cache, v)
  11024. } else {
  11025. if (arraysEqual(cache, elements)) return
  11026. mat4array.set(elements)
  11027. gl.uniformMatrix4fv(this.addr, false, mat4array)
  11028. copyArray(cache, elements)
  11029. }
  11030. }
  11031. // Single integer / boolean
  11032. function setValueV1i(gl, v) {
  11033. const cache = this.cache
  11034. if (cache[0] === v) return
  11035. gl.uniform1i(this.addr, v)
  11036. cache[0] = v
  11037. }
  11038. // Single integer / boolean vector (from flat array)
  11039. function setValueV2i(gl, v) {
  11040. const cache = this.cache
  11041. if (arraysEqual(cache, v)) return
  11042. gl.uniform2iv(this.addr, v)
  11043. copyArray(cache, v)
  11044. }
  11045. function setValueV3i(gl, v) {
  11046. const cache = this.cache
  11047. if (arraysEqual(cache, v)) return
  11048. gl.uniform3iv(this.addr, v)
  11049. copyArray(cache, v)
  11050. }
  11051. function setValueV4i(gl, v) {
  11052. const cache = this.cache
  11053. if (arraysEqual(cache, v)) return
  11054. gl.uniform4iv(this.addr, v)
  11055. copyArray(cache, v)
  11056. }
  11057. // Single unsigned integer
  11058. function setValueV1ui(gl, v) {
  11059. const cache = this.cache
  11060. if (cache[0] === v) return
  11061. gl.uniform1ui(this.addr, v)
  11062. cache[0] = v
  11063. }
  11064. // Single unsigned integer vector (from flat array)
  11065. function setValueV2ui(gl, v) {
  11066. const cache = this.cache
  11067. if (arraysEqual(cache, v)) return
  11068. gl.uniform2uiv(this.addr, v)
  11069. copyArray(cache, v)
  11070. }
  11071. function setValueV3ui(gl, v) {
  11072. const cache = this.cache
  11073. if (arraysEqual(cache, v)) return
  11074. gl.uniform3uiv(this.addr, v)
  11075. copyArray(cache, v)
  11076. }
  11077. function setValueV4ui(gl, v) {
  11078. const cache = this.cache
  11079. if (arraysEqual(cache, v)) return
  11080. gl.uniform4uiv(this.addr, v)
  11081. copyArray(cache, v)
  11082. }
  11083. // Single texture (2D / Cube)
  11084. function setValueT1(gl, v, textures) {
  11085. const cache = this.cache
  11086. const unit = textures.allocateTextureUnit()
  11087. if (cache[0] !== unit) {
  11088. gl.uniform1i(this.addr, unit)
  11089. cache[0] = unit
  11090. }
  11091. textures.setTexture2D(v || emptyTexture, unit)
  11092. }
  11093. function setValueT3D1(gl, v, textures) {
  11094. const cache = this.cache
  11095. const unit = textures.allocateTextureUnit()
  11096. if (cache[0] !== unit) {
  11097. gl.uniform1i(this.addr, unit)
  11098. cache[0] = unit
  11099. }
  11100. textures.setTexture3D(v || empty3dTexture, unit)
  11101. }
  11102. function setValueT6(gl, v, textures) {
  11103. const cache = this.cache
  11104. const unit = textures.allocateTextureUnit()
  11105. if (cache[0] !== unit) {
  11106. gl.uniform1i(this.addr, unit)
  11107. cache[0] = unit
  11108. }
  11109. textures.setTextureCube(v || emptyCubeTexture, unit)
  11110. }
  11111. function setValueT2DArray1(gl, v, textures) {
  11112. const cache = this.cache
  11113. const unit = textures.allocateTextureUnit()
  11114. if (cache[0] !== unit) {
  11115. gl.uniform1i(this.addr, unit)
  11116. cache[0] = unit
  11117. }
  11118. textures.setTexture2DArray(v || emptyArrayTexture, unit)
  11119. }
  11120. // Helper to pick the right setter for the singular case
  11121. function getSingularSetter(type) {
  11122. switch (type) {
  11123. case 0x1406:
  11124. return setValueV1f // FLOAT
  11125. case 0x8b50:
  11126. return setValueV2f // _VEC2
  11127. case 0x8b51:
  11128. return setValueV3f // _VEC3
  11129. case 0x8b52:
  11130. return setValueV4f // _VEC4
  11131. case 0x8b5a:
  11132. return setValueM2 // _MAT2
  11133. case 0x8b5b:
  11134. return setValueM3 // _MAT3
  11135. case 0x8b5c:
  11136. return setValueM4 // _MAT4
  11137. case 0x1404:
  11138. case 0x8b56:
  11139. return setValueV1i // INT, BOOL
  11140. case 0x8b53:
  11141. case 0x8b57:
  11142. return setValueV2i // _VEC2
  11143. case 0x8b54:
  11144. case 0x8b58:
  11145. return setValueV3i // _VEC3
  11146. case 0x8b55:
  11147. case 0x8b59:
  11148. return setValueV4i // _VEC4
  11149. case 0x1405:
  11150. return setValueV1ui // UINT
  11151. case 0x8dc6:
  11152. return setValueV2ui // _VEC2
  11153. case 0x8dc7:
  11154. return setValueV3ui // _VEC3
  11155. case 0x8dc8:
  11156. return setValueV4ui // _VEC4
  11157. case 0x8b5e: // SAMPLER_2D
  11158. case 0x8d66: // SAMPLER_EXTERNAL_OES
  11159. case 0x8dca: // INT_SAMPLER_2D
  11160. case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
  11161. case 0x8b62: // SAMPLER_2D_SHADOW
  11162. return setValueT1
  11163. case 0x8b5f: // SAMPLER_3D
  11164. case 0x8dcb: // INT_SAMPLER_3D
  11165. case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
  11166. return setValueT3D1
  11167. case 0x8b60: // SAMPLER_CUBE
  11168. case 0x8dcc: // INT_SAMPLER_CUBE
  11169. case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
  11170. case 0x8dc5: // SAMPLER_CUBE_SHADOW
  11171. return setValueT6
  11172. case 0x8dc1: // SAMPLER_2D_ARRAY
  11173. case 0x8dcf: // INT_SAMPLER_2D_ARRAY
  11174. case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
  11175. case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
  11176. return setValueT2DArray1
  11177. }
  11178. }
  11179. // Array of scalars
  11180. function setValueV1fArray(gl, v) {
  11181. gl.uniform1fv(this.addr, v)
  11182. }
  11183. // Array of vectors (from flat array or array of THREE.VectorN)
  11184. function setValueV2fArray(gl, v) {
  11185. const data = flatten(v, this.size, 2)
  11186. gl.uniform2fv(this.addr, data)
  11187. }
  11188. function setValueV3fArray(gl, v) {
  11189. const data = flatten(v, this.size, 3)
  11190. gl.uniform3fv(this.addr, data)
  11191. }
  11192. function setValueV4fArray(gl, v) {
  11193. const data = flatten(v, this.size, 4)
  11194. gl.uniform4fv(this.addr, data)
  11195. }
  11196. // Array of matrices (from flat array or array of THREE.MatrixN)
  11197. function setValueM2Array(gl, v) {
  11198. const data = flatten(v, this.size, 4)
  11199. gl.uniformMatrix2fv(this.addr, false, data)
  11200. }
  11201. function setValueM3Array(gl, v) {
  11202. const data = flatten(v, this.size, 9)
  11203. gl.uniformMatrix3fv(this.addr, false, data)
  11204. }
  11205. function setValueM4Array(gl, v) {
  11206. const data = flatten(v, this.size, 16)
  11207. gl.uniformMatrix4fv(this.addr, false, data)
  11208. }
  11209. // Array of integer / boolean
  11210. function setValueV1iArray(gl, v) {
  11211. gl.uniform1iv(this.addr, v)
  11212. }
  11213. // Array of integer / boolean vectors (from flat array)
  11214. function setValueV2iArray(gl, v) {
  11215. gl.uniform2iv(this.addr, v)
  11216. }
  11217. function setValueV3iArray(gl, v) {
  11218. gl.uniform3iv(this.addr, v)
  11219. }
  11220. function setValueV4iArray(gl, v) {
  11221. gl.uniform4iv(this.addr, v)
  11222. }
  11223. // Array of unsigned integer
  11224. function setValueV1uiArray(gl, v) {
  11225. gl.uniform1uiv(this.addr, v)
  11226. }
  11227. // Array of unsigned integer vectors (from flat array)
  11228. function setValueV2uiArray(gl, v) {
  11229. gl.uniform2uiv(this.addr, v)
  11230. }
  11231. function setValueV3uiArray(gl, v) {
  11232. gl.uniform3uiv(this.addr, v)
  11233. }
  11234. function setValueV4uiArray(gl, v) {
  11235. gl.uniform4uiv(this.addr, v)
  11236. }
  11237. // Array of textures (2D / 3D / Cube / 2DArray)
  11238. function setValueT1Array(gl, v, textures) {
  11239. const n = v.length
  11240. const units = allocTexUnits(textures, n)
  11241. gl.uniform1iv(this.addr, units)
  11242. for (let i = 0; i !== n; ++i) {
  11243. textures.setTexture2D(v[i] || emptyTexture, units[i])
  11244. }
  11245. }
  11246. function setValueT3DArray(gl, v, textures) {
  11247. const n = v.length
  11248. const units = allocTexUnits(textures, n)
  11249. gl.uniform1iv(this.addr, units)
  11250. for (let i = 0; i !== n; ++i) {
  11251. textures.setTexture3D(v[i] || empty3dTexture, units[i])
  11252. }
  11253. }
  11254. function setValueT6Array(gl, v, textures) {
  11255. const n = v.length
  11256. const units = allocTexUnits(textures, n)
  11257. gl.uniform1iv(this.addr, units)
  11258. for (let i = 0; i !== n; ++i) {
  11259. textures.setTextureCube(v[i] || emptyCubeTexture, units[i])
  11260. }
  11261. }
  11262. function setValueT2DArrayArray(gl, v, textures) {
  11263. const n = v.length
  11264. const units = allocTexUnits(textures, n)
  11265. gl.uniform1iv(this.addr, units)
  11266. for (let i = 0; i !== n; ++i) {
  11267. textures.setTexture2DArray(v[i] || emptyArrayTexture, units[i])
  11268. }
  11269. }
  11270. // Helper to pick the right setter for a pure (bottom-level) array
  11271. function getPureArraySetter(type) {
  11272. switch (type) {
  11273. case 0x1406:
  11274. return setValueV1fArray // FLOAT
  11275. case 0x8b50:
  11276. return setValueV2fArray // _VEC2
  11277. case 0x8b51:
  11278. return setValueV3fArray // _VEC3
  11279. case 0x8b52:
  11280. return setValueV4fArray // _VEC4
  11281. case 0x8b5a:
  11282. return setValueM2Array // _MAT2
  11283. case 0x8b5b:
  11284. return setValueM3Array // _MAT3
  11285. case 0x8b5c:
  11286. return setValueM4Array // _MAT4
  11287. case 0x1404:
  11288. case 0x8b56:
  11289. return setValueV1iArray // INT, BOOL
  11290. case 0x8b53:
  11291. case 0x8b57:
  11292. return setValueV2iArray // _VEC2
  11293. case 0x8b54:
  11294. case 0x8b58:
  11295. return setValueV3iArray // _VEC3
  11296. case 0x8b55:
  11297. case 0x8b59:
  11298. return setValueV4iArray // _VEC4
  11299. case 0x1405:
  11300. return setValueV1uiArray // UINT
  11301. case 0x8dc6:
  11302. return setValueV2uiArray // _VEC2
  11303. case 0x8dc7:
  11304. return setValueV3uiArray // _VEC3
  11305. case 0x8dc8:
  11306. return setValueV4uiArray // _VEC4
  11307. case 0x8b5e: // SAMPLER_2D
  11308. case 0x8d66: // SAMPLER_EXTERNAL_OES
  11309. case 0x8dca: // INT_SAMPLER_2D
  11310. case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
  11311. case 0x8b62: // SAMPLER_2D_SHADOW
  11312. return setValueT1Array
  11313. case 0x8b5f: // SAMPLER_3D
  11314. case 0x8dcb: // INT_SAMPLER_3D
  11315. case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
  11316. return setValueT3DArray
  11317. case 0x8b60: // SAMPLER_CUBE
  11318. case 0x8dcc: // INT_SAMPLER_CUBE
  11319. case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
  11320. case 0x8dc5: // SAMPLER_CUBE_SHADOW
  11321. return setValueT6Array
  11322. case 0x8dc1: // SAMPLER_2D_ARRAY
  11323. case 0x8dcf: // INT_SAMPLER_2D_ARRAY
  11324. case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
  11325. case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
  11326. return setValueT2DArrayArray
  11327. }
  11328. }
  11329. // --- Uniform Classes ---
  11330. class SingleUniform {
  11331. constructor(id, activeInfo, addr) {
  11332. this.id = id
  11333. this.addr = addr
  11334. this.cache = []
  11335. this.setValue = getSingularSetter(activeInfo.type)
  11336. // this.path = activeInfo.name; // DEBUG
  11337. }
  11338. }
  11339. class PureArrayUniform {
  11340. constructor(id, activeInfo, addr) {
  11341. this.id = id
  11342. this.addr = addr
  11343. this.cache = []
  11344. this.size = activeInfo.size
  11345. this.setValue = getPureArraySetter(activeInfo.type)
  11346. // this.path = activeInfo.name; // DEBUG
  11347. }
  11348. }
  11349. class StructuredUniform {
  11350. constructor(id) {
  11351. this.id = id
  11352. this.seq = []
  11353. this.map = {}
  11354. }
  11355. setValue(gl, value, textures) {
  11356. const seq = this.seq
  11357. for (let i = 0, n = seq.length; i !== n; ++i) {
  11358. const u = seq[i]
  11359. u.setValue(gl, value[u.id], textures)
  11360. }
  11361. }
  11362. }
  11363. // --- Top-level ---
  11364. // Parser - builds up the property tree from the path strings
  11365. const RePathPart = /(\w+)(\])?(\[|\.)?/g
  11366. // extracts
  11367. // - the identifier (member name or array index)
  11368. // - followed by an optional right bracket (found when array index)
  11369. // - followed by an optional left bracket or dot (type of subscript)
  11370. //
  11371. // Note: These portions can be read in a non-overlapping fashion and
  11372. // allow straightforward parsing of the hierarchy that WebGL encodes
  11373. // in the uniform names.
  11374. function addUniform(container, uniformObject) {
  11375. container.seq.push(uniformObject)
  11376. container.map[uniformObject.id] = uniformObject
  11377. }
  11378. function parseUniform(activeInfo, addr, container) {
  11379. const path = activeInfo.name,
  11380. pathLength = path.length
  11381. // reset RegExp object, because of the early exit of a previous run
  11382. RePathPart.lastIndex = 0
  11383. while (true) {
  11384. const match = RePathPart.exec(path),
  11385. matchEnd = RePathPart.lastIndex
  11386. let id = match[1]
  11387. const idIsIndex = match[2] === ']',
  11388. subscript = match[3]
  11389. if (idIsIndex) id = id | 0 // convert to integer
  11390. if (subscript === undefined || (subscript === '[' && matchEnd + 2 === pathLength)) {
  11391. // bare name or "pure" bottom-level array "[0]" suffix
  11392. addUniform(container, subscript === undefined ? new SingleUniform(id, activeInfo, addr) : new PureArrayUniform(id, activeInfo, addr))
  11393. break
  11394. } else {
  11395. // step into inner node / create it in case it doesn't exist
  11396. const map = container.map
  11397. let next = map[id]
  11398. if (next === undefined) {
  11399. next = new StructuredUniform(id)
  11400. addUniform(container, next)
  11401. }
  11402. container = next
  11403. }
  11404. }
  11405. }
  11406. // Root Container
  11407. class WebGLUniforms {
  11408. constructor(gl, program) {
  11409. this.seq = []
  11410. this.map = {}
  11411. const n = gl.getProgramParameter(program, 35718)
  11412. for (let i = 0; i < n; ++i) {
  11413. const info = gl.getActiveUniform(program, i),
  11414. addr = gl.getUniformLocation(program, info.name)
  11415. parseUniform(info, addr, this)
  11416. }
  11417. }
  11418. setValue(gl, name, value, textures) {
  11419. const u = this.map[name]
  11420. if (u !== undefined) u.setValue(gl, value, textures)
  11421. }
  11422. setOptional(gl, object, name) {
  11423. const v = object[name]
  11424. if (v !== undefined) this.setValue(gl, name, v)
  11425. }
  11426. static upload(gl, seq, values, textures) {
  11427. for (let i = 0, n = seq.length; i !== n; ++i) {
  11428. const u = seq[i],
  11429. v = values[u.id]
  11430. if (v.needsUpdate !== false) {
  11431. // note: always updating when .needsUpdate is undefined
  11432. u.setValue(gl, v.value, textures)
  11433. }
  11434. }
  11435. }
  11436. static seqWithValue(seq, values) {
  11437. const r = []
  11438. for (let i = 0, n = seq.length; i !== n; ++i) {
  11439. const u = seq[i]
  11440. if (u.id in values) r.push(u)
  11441. }
  11442. return r
  11443. }
  11444. }
  11445. function WebGLShader(gl, type, string) {
  11446. const shader = gl.createShader(type)
  11447. gl.shaderSource(shader, string)
  11448. gl.compileShader(shader)
  11449. return shader
  11450. }
  11451. let programIdCount = 0
  11452. function handleSource(string, errorLine) {
  11453. const lines = string.split('\n')
  11454. const lines2 = []
  11455. const from = Math.max(errorLine - 6, 0)
  11456. const to = Math.min(errorLine + 6, lines.length)
  11457. for (let i = from; i < to; i++) {
  11458. const line = i + 1
  11459. lines2.push(`${line === errorLine ? '>' : ' '} ${line}: ${lines[i]}`)
  11460. }
  11461. return lines2.join('\n')
  11462. }
  11463. function getEncodingComponents(encoding) {
  11464. switch (encoding) {
  11465. case LinearEncoding:
  11466. return ['Linear', '( value )']
  11467. case sRGBEncoding:
  11468. return ['sRGB', '( value )']
  11469. default:
  11470. console.warn('THREE.WebGLProgram: Unsupported encoding:', encoding)
  11471. return ['Linear', '( value )']
  11472. }
  11473. }
  11474. function getShaderErrors(gl, shader, type) {
  11475. const status = gl.getShaderParameter(shader, 35713)
  11476. const errors = gl.getShaderInfoLog(shader).trim()
  11477. if (status && errors === '') return ''
  11478. const errorMatches = /ERROR: 0:(\d+)/.exec(errors)
  11479. if (errorMatches) {
  11480. // --enable-privileged-webgl-extension
  11481. // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
  11482. const errorLine = parseInt(errorMatches[1])
  11483. return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource(gl.getShaderSource(shader), errorLine)
  11484. } else {
  11485. return errors
  11486. }
  11487. }
  11488. function getTexelEncodingFunction(functionName, encoding) {
  11489. const components = getEncodingComponents(encoding)
  11490. return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[0] + components[1] + '; }'
  11491. }
  11492. function getToneMappingFunction(functionName, toneMapping) {
  11493. let toneMappingName
  11494. switch (toneMapping) {
  11495. case LinearToneMapping:
  11496. toneMappingName = 'Linear'
  11497. break
  11498. case ReinhardToneMapping:
  11499. toneMappingName = 'Reinhard'
  11500. break
  11501. case CineonToneMapping:
  11502. toneMappingName = 'OptimizedCineon'
  11503. break
  11504. case ACESFilmicToneMapping:
  11505. toneMappingName = 'ACESFilmic'
  11506. break
  11507. case CustomToneMapping:
  11508. toneMappingName = 'Custom'
  11509. break
  11510. default:
  11511. console.warn('THREE.WebGLProgram: Unsupported toneMapping:', toneMapping)
  11512. toneMappingName = 'Linear'
  11513. }
  11514. return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'
  11515. }
  11516. function generateExtensions(parameters) {
  11517. const chunks = [
  11518. parameters.extensionDerivatives ||
  11519. !!parameters.envMapCubeUVHeight ||
  11520. parameters.bumpMap ||
  11521. parameters.tangentSpaceNormalMap ||
  11522. parameters.clearcoatNormalMap ||
  11523. parameters.flatShading ||
  11524. parameters.shaderID === 'physical'
  11525. ? '#extension GL_OES_standard_derivatives : enable'
  11526. : '',
  11527. (parameters.extensionFragDepth || parameters.logarithmicDepthBuffer) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
  11528. parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ? '#extension GL_EXT_draw_buffers : require' : '',
  11529. (parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
  11530. ]
  11531. return chunks.filter(filterEmptyLine).join('\n')
  11532. }
  11533. function generateDefines(defines) {
  11534. const chunks = []
  11535. for (const name in defines) {
  11536. const value = defines[name]
  11537. if (value === false) continue
  11538. chunks.push('#define ' + name + ' ' + value)
  11539. }
  11540. return chunks.join('\n')
  11541. }
  11542. function fetchAttributeLocations(gl, program) {
  11543. const attributes = {}
  11544. const n = gl.getProgramParameter(program, 35721)
  11545. for (let i = 0; i < n; i++) {
  11546. const info = gl.getActiveAttrib(program, i)
  11547. const name = info.name
  11548. let locationSize = 1
  11549. if (info.type === 35674) locationSize = 2
  11550. if (info.type === 35675) locationSize = 3
  11551. if (info.type === 35676) locationSize = 4
  11552. // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
  11553. attributes[name] = {
  11554. type: info.type,
  11555. location: gl.getAttribLocation(program, name),
  11556. locationSize: locationSize
  11557. }
  11558. }
  11559. return attributes
  11560. }
  11561. function filterEmptyLine(string) {
  11562. return string !== ''
  11563. }
  11564. function replaceLightNums(string, parameters) {
  11565. return string
  11566. .replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights)
  11567. .replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights)
  11568. .replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights)
  11569. .replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights)
  11570. .replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights)
  11571. .replace(/NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows)
  11572. .replace(/NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows)
  11573. .replace(/NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows)
  11574. }
  11575. function replaceClippingPlaneNums(string, parameters) {
  11576. return string.replace(/NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g, parameters.numClippingPlanes - parameters.numClipIntersection)
  11577. }
  11578. // Resolve Includes
  11579. const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm
  11580. function resolveIncludes(string) {
  11581. return string.replace(includePattern, includeReplacer)
  11582. }
  11583. function includeReplacer(match, include) {
  11584. const string = ShaderChunk[include]
  11585. if (string === undefined) {
  11586. throw new Error('Can not resolve #include <' + include + '>')
  11587. }
  11588. return resolveIncludes(string)
  11589. }
  11590. // Unroll Loops
  11591. const deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g
  11592. const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g
  11593. function unrollLoops(string) {
  11594. return string.replace(unrollLoopPattern, loopReplacer).replace(deprecatedUnrollLoopPattern, deprecatedLoopReplacer)
  11595. }
  11596. function deprecatedLoopReplacer(match, start, end, snippet) {
  11597. console.warn('WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.')
  11598. return loopReplacer(match, start, end, snippet)
  11599. }
  11600. function loopReplacer(match, start, end, snippet) {
  11601. let string = ''
  11602. for (let i = parseInt(start); i < parseInt(end); i++) {
  11603. string += snippet.replace(/\[\s*i\s*\]/g, '[ ' + i + ' ]').replace(/UNROLLED_LOOP_INDEX/g, i)
  11604. }
  11605. return string
  11606. }
  11607. //
  11608. function generatePrecision(parameters) {
  11609. let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;'
  11610. if (parameters.precision === 'highp') {
  11611. precisionstring += '\n#define HIGH_PRECISION'
  11612. } else if (parameters.precision === 'mediump') {
  11613. precisionstring += '\n#define MEDIUM_PRECISION'
  11614. } else if (parameters.precision === 'lowp') {
  11615. precisionstring += '\n#define LOW_PRECISION'
  11616. }
  11617. return precisionstring
  11618. }
  11619. function generateShadowMapTypeDefine(parameters) {
  11620. let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'
  11621. if (parameters.shadowMapType === PCFShadowMap) {
  11622. shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'
  11623. } else if (parameters.shadowMapType === PCFSoftShadowMap) {
  11624. shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'
  11625. } else if (parameters.shadowMapType === VSMShadowMap) {
  11626. shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'
  11627. }
  11628. return shadowMapTypeDefine
  11629. }
  11630. function generateEnvMapTypeDefine(parameters) {
  11631. let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'
  11632. if (parameters.envMap) {
  11633. switch (parameters.envMapMode) {
  11634. case CubeReflectionMapping:
  11635. case CubeRefractionMapping:
  11636. envMapTypeDefine = 'ENVMAP_TYPE_CUBE'
  11637. break
  11638. case CubeUVReflectionMapping:
  11639. envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'
  11640. break
  11641. }
  11642. }
  11643. return envMapTypeDefine
  11644. }
  11645. function generateEnvMapModeDefine(parameters) {
  11646. let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'
  11647. if (parameters.envMap) {
  11648. switch (parameters.envMapMode) {
  11649. case CubeRefractionMapping:
  11650. envMapModeDefine = 'ENVMAP_MODE_REFRACTION'
  11651. break
  11652. }
  11653. }
  11654. return envMapModeDefine
  11655. }
  11656. function generateEnvMapBlendingDefine(parameters) {
  11657. let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'
  11658. if (parameters.envMap) {
  11659. switch (parameters.combine) {
  11660. case MultiplyOperation:
  11661. envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'
  11662. break
  11663. case MixOperation:
  11664. envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'
  11665. break
  11666. case AddOperation:
  11667. envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'
  11668. break
  11669. }
  11670. }
  11671. return envMapBlendingDefine
  11672. }
  11673. function generateCubeUVSize(parameters) {
  11674. const imageHeight = parameters.envMapCubeUVHeight
  11675. if (imageHeight === null) return null
  11676. const maxMip = Math.log2(imageHeight) - 2
  11677. const texelHeight = 1.0 / imageHeight
  11678. const texelWidth = 1.0 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16))
  11679. return { texelWidth, texelHeight, maxMip }
  11680. }
  11681. function WebGLProgram(renderer, cacheKey, parameters, bindingStates) {
  11682. // TODO Send this event to Three.js DevTools
  11683. // console.log( 'WebGLProgram', cacheKey );
  11684. const gl = renderer.getContext()
  11685. const defines = parameters.defines
  11686. let vertexShader = parameters.vertexShader
  11687. let fragmentShader = parameters.fragmentShader
  11688. const shadowMapTypeDefine = generateShadowMapTypeDefine(parameters)
  11689. const envMapTypeDefine = generateEnvMapTypeDefine(parameters)
  11690. const envMapModeDefine = generateEnvMapModeDefine(parameters)
  11691. const envMapBlendingDefine = generateEnvMapBlendingDefine(parameters)
  11692. const envMapCubeUVSize = generateCubeUVSize(parameters)
  11693. const customExtensions = parameters.isWebGL2 ? '' : generateExtensions(parameters)
  11694. const customDefines = generateDefines(defines)
  11695. const program = gl.createProgram()
  11696. let prefixVertex, prefixFragment
  11697. let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''
  11698. if (parameters.isRawShaderMaterial) {
  11699. prefixVertex = [customDefines].filter(filterEmptyLine).join('\n')
  11700. if (prefixVertex.length > 0) {
  11701. prefixVertex += '\n'
  11702. }
  11703. prefixFragment = [customExtensions, customDefines].filter(filterEmptyLine).join('\n')
  11704. if (prefixFragment.length > 0) {
  11705. prefixFragment += '\n'
  11706. }
  11707. } else {
  11708. prefixVertex = [
  11709. generatePrecision(parameters),
  11710. '#define SHADER_NAME ' + parameters.shaderName,
  11711. customDefines,
  11712. parameters.instancing ? '#define USE_INSTANCING' : '',
  11713. parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
  11714. parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
  11715. parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
  11716. parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
  11717. parameters.map ? '#define USE_MAP' : '',
  11718. parameters.envMap ? '#define USE_ENVMAP' : '',
  11719. parameters.envMap ? '#define ' + envMapModeDefine : '',
  11720. parameters.lightMap ? '#define USE_LIGHTMAP' : '',
  11721. parameters.aoMap ? '#define USE_AOMAP' : '',
  11722. parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
  11723. parameters.bumpMap ? '#define USE_BUMPMAP' : '',
  11724. parameters.normalMap ? '#define USE_NORMALMAP' : '',
  11725. parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '',
  11726. parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '',
  11727. parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
  11728. parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
  11729. parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
  11730. parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
  11731. parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
  11732. parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
  11733. parameters.specularMap ? '#define USE_SPECULARMAP' : '',
  11734. parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
  11735. parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
  11736. parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
  11737. parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
  11738. parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
  11739. parameters.transmission ? '#define USE_TRANSMISSION' : '',
  11740. parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
  11741. parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
  11742. parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
  11743. parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
  11744. parameters.vertexTangents ? '#define USE_TANGENT' : '',
  11745. parameters.vertexColors ? '#define USE_COLOR' : '',
  11746. parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
  11747. parameters.vertexUvs ? '#define USE_UV' : '',
  11748. parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
  11749. parameters.flatShading ? '#define FLAT_SHADED' : '',
  11750. parameters.skinning ? '#define USE_SKINNING' : '',
  11751. parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
  11752. parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
  11753. parameters.morphColors && parameters.isWebGL2 ? '#define USE_MORPHCOLORS' : '',
  11754. parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE' : '',
  11755. parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '',
  11756. parameters.morphTargetsCount > 0 && parameters.isWebGL2 ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
  11757. parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
  11758. parameters.flipSided ? '#define FLIP_SIDED' : '',
  11759. parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
  11760. parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
  11761. parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
  11762. parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
  11763. parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '',
  11764. 'uniform mat4 modelMatrix;',
  11765. 'uniform mat4 modelViewMatrix;',
  11766. 'uniform mat4 projectionMatrix;',
  11767. 'uniform mat4 viewMatrix;',
  11768. 'uniform mat3 normalMatrix;',
  11769. 'uniform vec3 cameraPosition;',
  11770. 'uniform bool isOrthographic;',
  11771. '#ifdef USE_INSTANCING',
  11772. ' attribute mat4 instanceMatrix;',
  11773. '#endif',
  11774. '#ifdef USE_INSTANCING_COLOR',
  11775. ' attribute vec3 instanceColor;',
  11776. '#endif',
  11777. 'attribute vec3 position;',
  11778. 'attribute vec3 normal;',
  11779. 'attribute vec2 uv;',
  11780. '#ifdef USE_TANGENT',
  11781. ' attribute vec4 tangent;',
  11782. '#endif',
  11783. '#if defined( USE_COLOR_ALPHA )',
  11784. ' attribute vec4 color;',
  11785. '#elif defined( USE_COLOR )',
  11786. ' attribute vec3 color;',
  11787. '#endif',
  11788. '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
  11789. ' attribute vec3 morphTarget0;',
  11790. ' attribute vec3 morphTarget1;',
  11791. ' attribute vec3 morphTarget2;',
  11792. ' attribute vec3 morphTarget3;',
  11793. ' #ifdef USE_MORPHNORMALS',
  11794. ' attribute vec3 morphNormal0;',
  11795. ' attribute vec3 morphNormal1;',
  11796. ' attribute vec3 morphNormal2;',
  11797. ' attribute vec3 morphNormal3;',
  11798. ' #else',
  11799. ' attribute vec3 morphTarget4;',
  11800. ' attribute vec3 morphTarget5;',
  11801. ' attribute vec3 morphTarget6;',
  11802. ' attribute vec3 morphTarget7;',
  11803. ' #endif',
  11804. '#endif',
  11805. '#ifdef USE_SKINNING',
  11806. ' attribute vec4 skinIndex;',
  11807. ' attribute vec4 skinWeight;',
  11808. '#endif',
  11809. '\n'
  11810. ]
  11811. .filter(filterEmptyLine)
  11812. .join('\n')
  11813. prefixFragment = [
  11814. customExtensions,
  11815. generatePrecision(parameters),
  11816. '#define SHADER_NAME ' + parameters.shaderName,
  11817. customDefines,
  11818. parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
  11819. parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
  11820. parameters.map ? '#define USE_MAP' : '',
  11821. parameters.matcap ? '#define USE_MATCAP' : '',
  11822. parameters.envMap ? '#define USE_ENVMAP' : '',
  11823. parameters.envMap ? '#define ' + envMapTypeDefine : '',
  11824. parameters.envMap ? '#define ' + envMapModeDefine : '',
  11825. parameters.envMap ? '#define ' + envMapBlendingDefine : '',
  11826. envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
  11827. envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
  11828. envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
  11829. parameters.lightMap ? '#define USE_LIGHTMAP' : '',
  11830. parameters.aoMap ? '#define USE_AOMAP' : '',
  11831. parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
  11832. parameters.bumpMap ? '#define USE_BUMPMAP' : '',
  11833. parameters.normalMap ? '#define USE_NORMALMAP' : '',
  11834. parameters.normalMap && parameters.objectSpaceNormalMap ? '#define OBJECTSPACE_NORMALMAP' : '',
  11835. parameters.normalMap && parameters.tangentSpaceNormalMap ? '#define TANGENTSPACE_NORMALMAP' : '',
  11836. parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
  11837. parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
  11838. parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
  11839. parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
  11840. parameters.iridescence ? '#define USE_IRIDESCENCE' : '',
  11841. parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
  11842. parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
  11843. parameters.specularMap ? '#define USE_SPECULARMAP' : '',
  11844. parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
  11845. parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
  11846. parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
  11847. parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
  11848. parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
  11849. parameters.alphaTest ? '#define USE_ALPHATEST' : '',
  11850. parameters.sheen ? '#define USE_SHEEN' : '',
  11851. parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
  11852. parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
  11853. parameters.transmission ? '#define USE_TRANSMISSION' : '',
  11854. parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
  11855. parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
  11856. parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
  11857. parameters.vertexTangents ? '#define USE_TANGENT' : '',
  11858. parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
  11859. parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
  11860. parameters.vertexUvs ? '#define USE_UV' : '',
  11861. parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
  11862. parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
  11863. parameters.flatShading ? '#define FLAT_SHADED' : '',
  11864. parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
  11865. parameters.flipSided ? '#define FLIP_SIDED' : '',
  11866. parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
  11867. parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
  11868. parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
  11869. parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
  11870. parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
  11871. parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ? '#define USE_LOGDEPTHBUF_EXT' : '',
  11872. 'uniform mat4 viewMatrix;',
  11873. 'uniform vec3 cameraPosition;',
  11874. 'uniform bool isOrthographic;',
  11875. parameters.toneMapping !== NoToneMapping ? '#define TONE_MAPPING' : '',
  11876. parameters.toneMapping !== NoToneMapping ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below
  11877. parameters.toneMapping !== NoToneMapping ? getToneMappingFunction('toneMapping', parameters.toneMapping) : '',
  11878. parameters.dithering ? '#define DITHERING' : '',
  11879. parameters.opaque ? '#define OPAQUE' : '',
  11880. ShaderChunk['encodings_pars_fragment'], // this code is required here because it is used by the various encoding/decoding function defined below
  11881. getTexelEncodingFunction('linearToOutputTexel', parameters.outputEncoding),
  11882. parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
  11883. '\n'
  11884. ]
  11885. .filter(filterEmptyLine)
  11886. .join('\n')
  11887. }
  11888. vertexShader = resolveIncludes(vertexShader)
  11889. vertexShader = replaceLightNums(vertexShader, parameters)
  11890. vertexShader = replaceClippingPlaneNums(vertexShader, parameters)
  11891. fragmentShader = resolveIncludes(fragmentShader)
  11892. fragmentShader = replaceLightNums(fragmentShader, parameters)
  11893. fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters)
  11894. vertexShader = unrollLoops(vertexShader)
  11895. fragmentShader = unrollLoops(fragmentShader)
  11896. if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) {
  11897. // GLSL 3.0 conversion for built-in materials and ShaderMaterial
  11898. versionString = '#version 300 es\n'
  11899. prefixVertex = ['precision mediump sampler2DArray;', '#define attribute in', '#define varying out', '#define texture2D texture'].join('\n') + '\n' + prefixVertex
  11900. prefixFragment =
  11901. [
  11902. '#define varying in',
  11903. parameters.glslVersion === GLSL3 ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;',
  11904. parameters.glslVersion === GLSL3 ? '' : '#define gl_FragColor pc_fragColor',
  11905. '#define gl_FragDepthEXT gl_FragDepth',
  11906. '#define texture2D texture',
  11907. '#define textureCube texture',
  11908. '#define texture2DProj textureProj',
  11909. '#define texture2DLodEXT textureLod',
  11910. '#define texture2DProjLodEXT textureProjLod',
  11911. '#define textureCubeLodEXT textureLod',
  11912. '#define texture2DGradEXT textureGrad',
  11913. '#define texture2DProjGradEXT textureProjGrad',
  11914. '#define textureCubeGradEXT textureGrad'
  11915. ].join('\n') +
  11916. '\n' +
  11917. prefixFragment
  11918. }
  11919. const vertexGlsl = versionString + prefixVertex + vertexShader
  11920. const fragmentGlsl = versionString + prefixFragment + fragmentShader
  11921. // console.log( '*VERTEX*', vertexGlsl );
  11922. // console.log( '*FRAGMENT*', fragmentGlsl );
  11923. const glVertexShader = WebGLShader(gl, 35633, vertexGlsl)
  11924. const glFragmentShader = WebGLShader(gl, 35632, fragmentGlsl)
  11925. gl.attachShader(program, glVertexShader)
  11926. gl.attachShader(program, glFragmentShader)
  11927. // Force a particular attribute to index 0.
  11928. if (parameters.index0AttributeName !== undefined) {
  11929. gl.bindAttribLocation(program, 0, parameters.index0AttributeName)
  11930. } else if (parameters.morphTargets === true) {
  11931. // programs with morphTargets displace position out of attribute 0
  11932. gl.bindAttribLocation(program, 0, 'position')
  11933. }
  11934. gl.linkProgram(program)
  11935. // check for link errors
  11936. if (renderer.debug.checkShaderErrors) {
  11937. const programLog = gl.getProgramInfoLog(program).trim()
  11938. const vertexLog = gl.getShaderInfoLog(glVertexShader).trim()
  11939. const fragmentLog = gl.getShaderInfoLog(glFragmentShader).trim()
  11940. let runnable = true
  11941. let haveDiagnostics = true
  11942. if (gl.getProgramParameter(program, 35714) === false) {
  11943. runnable = false
  11944. const vertexErrors = getShaderErrors(gl, glVertexShader, 'vertex')
  11945. const fragmentErrors = getShaderErrors(gl, glFragmentShader, 'fragment')
  11946. console.error(
  11947. 'THREE.WebGLProgram: Shader Error ' +
  11948. gl.getError() +
  11949. ' - ' +
  11950. 'VALIDATE_STATUS ' +
  11951. gl.getProgramParameter(program, 35715) +
  11952. '\n\n' +
  11953. 'Program Info Log: ' +
  11954. programLog +
  11955. '\n' +
  11956. vertexErrors +
  11957. '\n' +
  11958. fragmentErrors
  11959. )
  11960. } else if (programLog !== '') {
  11961. console.warn('THREE.WebGLProgram: Program Info Log:', programLog)
  11962. } else if (vertexLog === '' || fragmentLog === '') {
  11963. haveDiagnostics = false
  11964. }
  11965. if (haveDiagnostics) {
  11966. this.diagnostics = {
  11967. runnable: runnable,
  11968. programLog: programLog,
  11969. vertexShader: {
  11970. log: vertexLog,
  11971. prefix: prefixVertex
  11972. },
  11973. fragmentShader: {
  11974. log: fragmentLog,
  11975. prefix: prefixFragment
  11976. }
  11977. }
  11978. }
  11979. }
  11980. // Clean up
  11981. // Crashes in iOS9 and iOS10. #18402
  11982. // gl.detachShader( program, glVertexShader );
  11983. // gl.detachShader( program, glFragmentShader );
  11984. gl.deleteShader(glVertexShader)
  11985. gl.deleteShader(glFragmentShader)
  11986. // set up caching for uniform locations
  11987. let cachedUniforms
  11988. this.getUniforms = function() {
  11989. if (cachedUniforms === undefined) {
  11990. cachedUniforms = new WebGLUniforms(gl, program)
  11991. }
  11992. return cachedUniforms
  11993. }
  11994. // set up caching for attribute locations
  11995. let cachedAttributes
  11996. this.getAttributes = function() {
  11997. if (cachedAttributes === undefined) {
  11998. cachedAttributes = fetchAttributeLocations(gl, program)
  11999. }
  12000. return cachedAttributes
  12001. }
  12002. // free resource
  12003. this.destroy = function() {
  12004. bindingStates.releaseStatesOfProgram(this)
  12005. gl.deleteProgram(program)
  12006. this.program = undefined
  12007. }
  12008. //
  12009. this.name = parameters.shaderName
  12010. this.id = programIdCount++
  12011. this.cacheKey = cacheKey
  12012. this.usedTimes = 1
  12013. this.program = program
  12014. this.vertexShader = glVertexShader
  12015. this.fragmentShader = glFragmentShader
  12016. return this
  12017. }
  12018. let _id = 0
  12019. class WebGLShaderCache {
  12020. constructor() {
  12021. this.shaderCache = new Map()
  12022. this.materialCache = new Map()
  12023. }
  12024. update(material) {
  12025. const vertexShader = material.vertexShader
  12026. const fragmentShader = material.fragmentShader
  12027. const vertexShaderStage = this._getShaderStage(vertexShader)
  12028. const fragmentShaderStage = this._getShaderStage(fragmentShader)
  12029. const materialShaders = this._getShaderCacheForMaterial(material)
  12030. if (materialShaders.has(vertexShaderStage) === false) {
  12031. materialShaders.add(vertexShaderStage)
  12032. vertexShaderStage.usedTimes++
  12033. }
  12034. if (materialShaders.has(fragmentShaderStage) === false) {
  12035. materialShaders.add(fragmentShaderStage)
  12036. fragmentShaderStage.usedTimes++
  12037. }
  12038. return this
  12039. }
  12040. remove(material) {
  12041. const materialShaders = this.materialCache.get(material)
  12042. for (const shaderStage of materialShaders) {
  12043. shaderStage.usedTimes--
  12044. if (shaderStage.usedTimes === 0) this.shaderCache.delete(shaderStage.code)
  12045. }
  12046. this.materialCache.delete(material)
  12047. return this
  12048. }
  12049. getVertexShaderID(material) {
  12050. return this._getShaderStage(material.vertexShader).id
  12051. }
  12052. getFragmentShaderID(material) {
  12053. return this._getShaderStage(material.fragmentShader).id
  12054. }
  12055. dispose() {
  12056. this.shaderCache.clear()
  12057. this.materialCache.clear()
  12058. }
  12059. _getShaderCacheForMaterial(material) {
  12060. const cache = this.materialCache
  12061. if (cache.has(material) === false) {
  12062. cache.set(material, new Set())
  12063. }
  12064. return cache.get(material)
  12065. }
  12066. _getShaderStage(code) {
  12067. const cache = this.shaderCache
  12068. if (cache.has(code) === false) {
  12069. const stage = new WebGLShaderStage(code)
  12070. cache.set(code, stage)
  12071. }
  12072. return cache.get(code)
  12073. }
  12074. }
  12075. class WebGLShaderStage {
  12076. constructor(code) {
  12077. this.id = _id++
  12078. this.code = code
  12079. this.usedTimes = 0
  12080. }
  12081. }
  12082. function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) {
  12083. const _programLayers = new Layers()
  12084. const _customShaders = new WebGLShaderCache()
  12085. const programs = []
  12086. const isWebGL2 = capabilities.isWebGL2
  12087. const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer
  12088. const vertexTextures = capabilities.vertexTextures
  12089. let precision = capabilities.precision
  12090. const shaderIDs = {
  12091. MeshDepthMaterial: 'depth',
  12092. MeshDistanceMaterial: 'distanceRGBA',
  12093. MeshNormalMaterial: 'normal',
  12094. MeshBasicMaterial: 'basic',
  12095. MeshLambertMaterial: 'lambert',
  12096. MeshPhongMaterial: 'phong',
  12097. MeshToonMaterial: 'toon',
  12098. MeshStandardMaterial: 'physical',
  12099. MeshPhysicalMaterial: 'physical',
  12100. MeshMatcapMaterial: 'matcap',
  12101. LineBasicMaterial: 'basic',
  12102. LineDashedMaterial: 'dashed',
  12103. PointsMaterial: 'points',
  12104. ShadowMaterial: 'shadow',
  12105. SpriteMaterial: 'sprite'
  12106. }
  12107. function getParameters(material, lights, shadows, scene, object) {
  12108. const fog = scene.fog
  12109. const geometry = object.geometry
  12110. const environment = material.isMeshStandardMaterial ? scene.environment : null
  12111. const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment)
  12112. const envMapCubeUVHeight = !!envMap && envMap.mapping === CubeUVReflectionMapping ? envMap.image.height : null
  12113. const shaderID = shaderIDs[material.type]
  12114. // heuristics to create shader parameters according to lights in the scene
  12115. // (not to blow over maxLights budget)
  12116. if (material.precision !== null) {
  12117. precision = capabilities.getMaxPrecision(material.precision)
  12118. if (precision !== material.precision) {
  12119. console.warn('THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.')
  12120. }
  12121. }
  12122. //
  12123. const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color
  12124. const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0
  12125. let morphTextureStride = 0
  12126. if (geometry.morphAttributes.position !== undefined) morphTextureStride = 1
  12127. if (geometry.morphAttributes.normal !== undefined) morphTextureStride = 2
  12128. if (geometry.morphAttributes.color !== undefined) morphTextureStride = 3
  12129. //
  12130. let vertexShader, fragmentShader
  12131. let customVertexShaderID, customFragmentShaderID
  12132. if (shaderID) {
  12133. const shader = ShaderLib[shaderID]
  12134. vertexShader = shader.vertexShader
  12135. fragmentShader = shader.fragmentShader
  12136. } else {
  12137. vertexShader = material.vertexShader
  12138. fragmentShader = material.fragmentShader
  12139. _customShaders.update(material)
  12140. customVertexShaderID = _customShaders.getVertexShaderID(material)
  12141. customFragmentShaderID = _customShaders.getFragmentShaderID(material)
  12142. }
  12143. const currentRenderTarget = renderer.getRenderTarget()
  12144. const useAlphaTest = material.alphaTest > 0
  12145. const useClearcoat = material.clearcoat > 0
  12146. const useIridescence = material.iridescence > 0
  12147. const parameters = {
  12148. isWebGL2: isWebGL2,
  12149. shaderID: shaderID,
  12150. shaderName: material.type,
  12151. vertexShader: vertexShader,
  12152. fragmentShader: fragmentShader,
  12153. defines: material.defines,
  12154. customVertexShaderID: customVertexShaderID,
  12155. customFragmentShaderID: customFragmentShaderID,
  12156. isRawShaderMaterial: material.isRawShaderMaterial === true,
  12157. glslVersion: material.glslVersion,
  12158. precision: precision,
  12159. instancing: object.isInstancedMesh === true,
  12160. instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
  12161. supportsVertexTextures: vertexTextures,
  12162. outputEncoding: currentRenderTarget === null ? renderer.outputEncoding : currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding,
  12163. map: !!material.map,
  12164. matcap: !!material.matcap,
  12165. envMap: !!envMap,
  12166. envMapMode: envMap && envMap.mapping,
  12167. envMapCubeUVHeight: envMapCubeUVHeight,
  12168. lightMap: !!material.lightMap,
  12169. aoMap: !!material.aoMap,
  12170. emissiveMap: !!material.emissiveMap,
  12171. bumpMap: !!material.bumpMap,
  12172. normalMap: !!material.normalMap,
  12173. objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
  12174. tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
  12175. decodeVideoTexture: !!material.map && material.map.isVideoTexture === true && material.map.encoding === sRGBEncoding,
  12176. clearcoat: useClearcoat,
  12177. clearcoatMap: useClearcoat && !!material.clearcoatMap,
  12178. clearcoatRoughnessMap: useClearcoat && !!material.clearcoatRoughnessMap,
  12179. clearcoatNormalMap: useClearcoat && !!material.clearcoatNormalMap,
  12180. iridescence: useIridescence,
  12181. iridescenceMap: useIridescence && !!material.iridescenceMap,
  12182. iridescenceThicknessMap: useIridescence && !!material.iridescenceThicknessMap,
  12183. displacementMap: !!material.displacementMap,
  12184. roughnessMap: !!material.roughnessMap,
  12185. metalnessMap: !!material.metalnessMap,
  12186. specularMap: !!material.specularMap,
  12187. specularIntensityMap: !!material.specularIntensityMap,
  12188. specularColorMap: !!material.specularColorMap,
  12189. opaque: material.transparent === false && material.blending === NormalBlending,
  12190. alphaMap: !!material.alphaMap,
  12191. alphaTest: useAlphaTest,
  12192. gradientMap: !!material.gradientMap,
  12193. sheen: material.sheen > 0,
  12194. sheenColorMap: !!material.sheenColorMap,
  12195. sheenRoughnessMap: !!material.sheenRoughnessMap,
  12196. transmission: material.transmission > 0,
  12197. transmissionMap: !!material.transmissionMap,
  12198. thicknessMap: !!material.thicknessMap,
  12199. combine: material.combine,
  12200. vertexTangents: !!material.normalMap && !!geometry.attributes.tangent,
  12201. vertexColors: material.vertexColors,
  12202. vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4,
  12203. vertexUvs:
  12204. !!material.map ||
  12205. !!material.bumpMap ||
  12206. !!material.normalMap ||
  12207. !!material.specularMap ||
  12208. !!material.alphaMap ||
  12209. !!material.emissiveMap ||
  12210. !!material.roughnessMap ||
  12211. !!material.metalnessMap ||
  12212. !!material.clearcoatMap ||
  12213. !!material.clearcoatRoughnessMap ||
  12214. !!material.clearcoatNormalMap ||
  12215. !!material.iridescenceMap ||
  12216. !!material.iridescenceThicknessMap ||
  12217. !!material.displacementMap ||
  12218. !!material.transmissionMap ||
  12219. !!material.thicknessMap ||
  12220. !!material.specularIntensityMap ||
  12221. !!material.specularColorMap ||
  12222. !!material.sheenColorMap ||
  12223. !!material.sheenRoughnessMap,
  12224. uvsVertexOnly:
  12225. !(
  12226. !!material.map ||
  12227. !!material.bumpMap ||
  12228. !!material.normalMap ||
  12229. !!material.specularMap ||
  12230. !!material.alphaMap ||
  12231. !!material.emissiveMap ||
  12232. !!material.roughnessMap ||
  12233. !!material.metalnessMap ||
  12234. !!material.clearcoatNormalMap ||
  12235. !!material.iridescenceMap ||
  12236. !!material.iridescenceThicknessMap ||
  12237. material.transmission > 0 ||
  12238. !!material.transmissionMap ||
  12239. !!material.thicknessMap ||
  12240. !!material.specularIntensityMap ||
  12241. !!material.specularColorMap ||
  12242. material.sheen > 0 ||
  12243. !!material.sheenColorMap ||
  12244. !!material.sheenRoughnessMap
  12245. ) && !!material.displacementMap,
  12246. fog: !!fog,
  12247. useFog: material.fog === true,
  12248. fogExp2: fog && fog.isFogExp2,
  12249. flatShading: !!material.flatShading,
  12250. sizeAttenuation: material.sizeAttenuation,
  12251. logarithmicDepthBuffer: logarithmicDepthBuffer,
  12252. skinning: object.isSkinnedMesh === true,
  12253. morphTargets: geometry.morphAttributes.position !== undefined,
  12254. morphNormals: geometry.morphAttributes.normal !== undefined,
  12255. morphColors: geometry.morphAttributes.color !== undefined,
  12256. morphTargetsCount: morphTargetsCount,
  12257. morphTextureStride: morphTextureStride,
  12258. numDirLights: lights.directional.length,
  12259. numPointLights: lights.point.length,
  12260. numSpotLights: lights.spot.length,
  12261. numRectAreaLights: lights.rectArea.length,
  12262. numHemiLights: lights.hemi.length,
  12263. numDirLightShadows: lights.directionalShadowMap.length,
  12264. numPointLightShadows: lights.pointShadowMap.length,
  12265. numSpotLightShadows: lights.spotShadowMap.length,
  12266. numClippingPlanes: clipping.numPlanes,
  12267. numClipIntersection: clipping.numIntersection,
  12268. dithering: material.dithering,
  12269. shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
  12270. shadowMapType: renderer.shadowMap.type,
  12271. toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
  12272. physicallyCorrectLights: renderer.physicallyCorrectLights,
  12273. premultipliedAlpha: material.premultipliedAlpha,
  12274. doubleSided: material.side === DoubleSide,
  12275. flipSided: material.side === BackSide,
  12276. useDepthPacking: !!material.depthPacking,
  12277. depthPacking: material.depthPacking || 0,
  12278. index0AttributeName: material.index0AttributeName,
  12279. extensionDerivatives: material.extensions && material.extensions.derivatives,
  12280. extensionFragDepth: material.extensions && material.extensions.fragDepth,
  12281. extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
  12282. extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
  12283. rendererExtensionFragDepth: isWebGL2 || extensions.has('EXT_frag_depth'),
  12284. rendererExtensionDrawBuffers: isWebGL2 || extensions.has('WEBGL_draw_buffers'),
  12285. rendererExtensionShaderTextureLod: isWebGL2 || extensions.has('EXT_shader_texture_lod'),
  12286. customProgramCacheKey: material.customProgramCacheKey()
  12287. }
  12288. return parameters
  12289. }
  12290. function getProgramCacheKey(parameters) {
  12291. const array = []
  12292. if (parameters.shaderID) {
  12293. array.push(parameters.shaderID)
  12294. } else {
  12295. array.push(parameters.customVertexShaderID)
  12296. array.push(parameters.customFragmentShaderID)
  12297. }
  12298. if (parameters.defines !== undefined) {
  12299. for (const name in parameters.defines) {
  12300. array.push(name)
  12301. array.push(parameters.defines[name])
  12302. }
  12303. }
  12304. if (parameters.isRawShaderMaterial === false) {
  12305. getProgramCacheKeyParameters(array, parameters)
  12306. getProgramCacheKeyBooleans(array, parameters)
  12307. array.push(renderer.outputEncoding)
  12308. }
  12309. array.push(parameters.customProgramCacheKey)
  12310. return array.join()
  12311. }
  12312. function getProgramCacheKeyParameters(array, parameters) {
  12313. array.push(parameters.precision)
  12314. array.push(parameters.outputEncoding)
  12315. array.push(parameters.envMapMode)
  12316. array.push(parameters.envMapCubeUVHeight)
  12317. array.push(parameters.combine)
  12318. array.push(parameters.vertexUvs)
  12319. array.push(parameters.fogExp2)
  12320. array.push(parameters.sizeAttenuation)
  12321. array.push(parameters.morphTargetsCount)
  12322. array.push(parameters.morphAttributeCount)
  12323. array.push(parameters.numDirLights)
  12324. array.push(parameters.numPointLights)
  12325. array.push(parameters.numSpotLights)
  12326. array.push(parameters.numHemiLights)
  12327. array.push(parameters.numRectAreaLights)
  12328. array.push(parameters.numDirLightShadows)
  12329. array.push(parameters.numPointLightShadows)
  12330. array.push(parameters.numSpotLightShadows)
  12331. array.push(parameters.shadowMapType)
  12332. array.push(parameters.toneMapping)
  12333. array.push(parameters.numClippingPlanes)
  12334. array.push(parameters.numClipIntersection)
  12335. array.push(parameters.depthPacking)
  12336. }
  12337. function getProgramCacheKeyBooleans(array, parameters) {
  12338. _programLayers.disableAll()
  12339. if (parameters.isWebGL2) _programLayers.enable(0)
  12340. if (parameters.supportsVertexTextures) _programLayers.enable(1)
  12341. if (parameters.instancing) _programLayers.enable(2)
  12342. if (parameters.instancingColor) _programLayers.enable(3)
  12343. if (parameters.map) _programLayers.enable(4)
  12344. if (parameters.matcap) _programLayers.enable(5)
  12345. if (parameters.envMap) _programLayers.enable(6)
  12346. if (parameters.lightMap) _programLayers.enable(7)
  12347. if (parameters.aoMap) _programLayers.enable(8)
  12348. if (parameters.emissiveMap) _programLayers.enable(9)
  12349. if (parameters.bumpMap) _programLayers.enable(10)
  12350. if (parameters.normalMap) _programLayers.enable(11)
  12351. if (parameters.objectSpaceNormalMap) _programLayers.enable(12)
  12352. if (parameters.tangentSpaceNormalMap) _programLayers.enable(13)
  12353. if (parameters.clearcoat) _programLayers.enable(14)
  12354. if (parameters.clearcoatMap) _programLayers.enable(15)
  12355. if (parameters.clearcoatRoughnessMap) _programLayers.enable(16)
  12356. if (parameters.clearcoatNormalMap) _programLayers.enable(17)
  12357. if (parameters.iridescence) _programLayers.enable(18)
  12358. if (parameters.iridescenceMap) _programLayers.enable(19)
  12359. if (parameters.iridescenceThicknessMap) _programLayers.enable(20)
  12360. if (parameters.displacementMap) _programLayers.enable(21)
  12361. if (parameters.specularMap) _programLayers.enable(22)
  12362. if (parameters.roughnessMap) _programLayers.enable(23)
  12363. if (parameters.metalnessMap) _programLayers.enable(24)
  12364. if (parameters.gradientMap) _programLayers.enable(25)
  12365. if (parameters.alphaMap) _programLayers.enable(26)
  12366. if (parameters.alphaTest) _programLayers.enable(27)
  12367. if (parameters.vertexColors) _programLayers.enable(28)
  12368. if (parameters.vertexAlphas) _programLayers.enable(29)
  12369. if (parameters.vertexUvs) _programLayers.enable(30)
  12370. if (parameters.vertexTangents) _programLayers.enable(31)
  12371. if (parameters.uvsVertexOnly) _programLayers.enable(32)
  12372. if (parameters.fog) _programLayers.enable(33)
  12373. array.push(_programLayers.mask)
  12374. _programLayers.disableAll()
  12375. if (parameters.useFog) _programLayers.enable(0)
  12376. if (parameters.flatShading) _programLayers.enable(1)
  12377. if (parameters.logarithmicDepthBuffer) _programLayers.enable(2)
  12378. if (parameters.skinning) _programLayers.enable(3)
  12379. if (parameters.morphTargets) _programLayers.enable(4)
  12380. if (parameters.morphNormals) _programLayers.enable(5)
  12381. if (parameters.morphColors) _programLayers.enable(6)
  12382. if (parameters.premultipliedAlpha) _programLayers.enable(7)
  12383. if (parameters.shadowMapEnabled) _programLayers.enable(8)
  12384. if (parameters.physicallyCorrectLights) _programLayers.enable(9)
  12385. if (parameters.doubleSided) _programLayers.enable(10)
  12386. if (parameters.flipSided) _programLayers.enable(11)
  12387. if (parameters.useDepthPacking) _programLayers.enable(12)
  12388. if (parameters.dithering) _programLayers.enable(13)
  12389. if (parameters.specularIntensityMap) _programLayers.enable(14)
  12390. if (parameters.specularColorMap) _programLayers.enable(15)
  12391. if (parameters.transmission) _programLayers.enable(16)
  12392. if (parameters.transmissionMap) _programLayers.enable(17)
  12393. if (parameters.thicknessMap) _programLayers.enable(18)
  12394. if (parameters.sheen) _programLayers.enable(19)
  12395. if (parameters.sheenColorMap) _programLayers.enable(20)
  12396. if (parameters.sheenRoughnessMap) _programLayers.enable(21)
  12397. if (parameters.decodeVideoTexture) _programLayers.enable(22)
  12398. if (parameters.opaque) _programLayers.enable(23)
  12399. array.push(_programLayers.mask)
  12400. }
  12401. function getUniforms(material) {
  12402. const shaderID = shaderIDs[material.type]
  12403. let uniforms
  12404. if (shaderID) {
  12405. const shader = ShaderLib[shaderID]
  12406. uniforms = UniformsUtils.clone(shader.uniforms)
  12407. } else {
  12408. uniforms = material.uniforms
  12409. }
  12410. return uniforms
  12411. }
  12412. function acquireProgram(parameters, cacheKey) {
  12413. let program
  12414. // Check if code has been already compiled
  12415. for (let p = 0, pl = programs.length; p < pl; p++) {
  12416. const preexistingProgram = programs[p]
  12417. if (preexistingProgram.cacheKey === cacheKey) {
  12418. program = preexistingProgram
  12419. ++program.usedTimes
  12420. break
  12421. }
  12422. }
  12423. if (program === undefined) {
  12424. program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates)
  12425. programs.push(program)
  12426. }
  12427. return program
  12428. }
  12429. function releaseProgram(program) {
  12430. if (--program.usedTimes === 0) {
  12431. // Remove from unordered set
  12432. const i = programs.indexOf(program)
  12433. programs[i] = programs[programs.length - 1]
  12434. programs.pop()
  12435. // Free WebGL resources
  12436. program.destroy()
  12437. }
  12438. }
  12439. function releaseShaderCache(material) {
  12440. _customShaders.remove(material)
  12441. }
  12442. function dispose() {
  12443. _customShaders.dispose()
  12444. }
  12445. return {
  12446. getParameters: getParameters,
  12447. getProgramCacheKey: getProgramCacheKey,
  12448. getUniforms: getUniforms,
  12449. acquireProgram: acquireProgram,
  12450. releaseProgram: releaseProgram,
  12451. releaseShaderCache: releaseShaderCache,
  12452. // Exposed for resource monitoring & error feedback via renderer.info:
  12453. programs: programs,
  12454. dispose: dispose
  12455. }
  12456. }
  12457. function WebGLProperties() {
  12458. let properties = new WeakMap()
  12459. function get(object) {
  12460. let map = properties.get(object)
  12461. if (map === undefined) {
  12462. map = {}
  12463. properties.set(object, map)
  12464. }
  12465. return map
  12466. }
  12467. function remove(object) {
  12468. properties.delete(object)
  12469. }
  12470. function update(object, key, value) {
  12471. properties.get(object)[key] = value
  12472. }
  12473. function dispose() {
  12474. properties = new WeakMap()
  12475. }
  12476. return {
  12477. get: get,
  12478. remove: remove,
  12479. update: update,
  12480. dispose: dispose
  12481. }
  12482. }
  12483. function painterSortStable(a, b) {
  12484. if (a.groupOrder !== b.groupOrder) {
  12485. return a.groupOrder - b.groupOrder
  12486. } else if (a.renderOrder !== b.renderOrder) {
  12487. return a.renderOrder - b.renderOrder
  12488. } else if (a.material.id !== b.material.id) {
  12489. return a.material.id - b.material.id
  12490. } else if (a.z !== b.z) {
  12491. return a.z - b.z
  12492. } else {
  12493. return a.id - b.id
  12494. }
  12495. }
  12496. function reversePainterSortStable(a, b) {
  12497. if (a.groupOrder !== b.groupOrder) {
  12498. return a.groupOrder - b.groupOrder
  12499. } else if (a.renderOrder !== b.renderOrder) {
  12500. return a.renderOrder - b.renderOrder
  12501. } else if (a.z !== b.z) {
  12502. return b.z - a.z
  12503. } else {
  12504. return a.id - b.id
  12505. }
  12506. }
  12507. function WebGLRenderList() {
  12508. const renderItems = []
  12509. let renderItemsIndex = 0
  12510. const opaque = []
  12511. const transmissive = []
  12512. const transparent = []
  12513. function init() {
  12514. renderItemsIndex = 0
  12515. opaque.length = 0
  12516. transmissive.length = 0
  12517. transparent.length = 0
  12518. }
  12519. function getNextRenderItem(object, geometry, material, groupOrder, z, group) {
  12520. let renderItem = renderItems[renderItemsIndex]
  12521. if (renderItem === undefined) {
  12522. renderItem = {
  12523. id: object.id,
  12524. object: object,
  12525. geometry: geometry,
  12526. material: material,
  12527. groupOrder: groupOrder,
  12528. renderOrder: object.renderOrder,
  12529. z: z,
  12530. group: group
  12531. }
  12532. renderItems[renderItemsIndex] = renderItem
  12533. } else {
  12534. renderItem.id = object.id
  12535. renderItem.object = object
  12536. renderItem.geometry = geometry
  12537. renderItem.material = material
  12538. renderItem.groupOrder = groupOrder
  12539. renderItem.renderOrder = object.renderOrder
  12540. renderItem.z = z
  12541. renderItem.group = group
  12542. }
  12543. renderItemsIndex++
  12544. return renderItem
  12545. }
  12546. function push(object, geometry, material, groupOrder, z, group) {
  12547. const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group)
  12548. if (material.transmission > 0.0) {
  12549. transmissive.push(renderItem)
  12550. } else if (material.transparent === true) {
  12551. transparent.push(renderItem)
  12552. } else {
  12553. opaque.push(renderItem)
  12554. }
  12555. }
  12556. function unshift(object, geometry, material, groupOrder, z, group) {
  12557. const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group)
  12558. if (material.transmission > 0.0) {
  12559. transmissive.unshift(renderItem)
  12560. } else if (material.transparent === true) {
  12561. transparent.unshift(renderItem)
  12562. } else {
  12563. opaque.unshift(renderItem)
  12564. }
  12565. }
  12566. function sort(customOpaqueSort, customTransparentSort) {
  12567. if (opaque.length > 1) opaque.sort(customOpaqueSort || painterSortStable)
  12568. if (transmissive.length > 1) transmissive.sort(customTransparentSort || reversePainterSortStable)
  12569. if (transparent.length > 1) transparent.sort(customTransparentSort || reversePainterSortStable)
  12570. }
  12571. function finish() {
  12572. // Clear references from inactive renderItems in the list
  12573. for (let i = renderItemsIndex, il = renderItems.length; i < il; i++) {
  12574. const renderItem = renderItems[i]
  12575. if (renderItem.id === null) break
  12576. renderItem.id = null
  12577. renderItem.object = null
  12578. renderItem.geometry = null
  12579. renderItem.material = null
  12580. renderItem.group = null
  12581. }
  12582. }
  12583. return {
  12584. opaque: opaque,
  12585. transmissive: transmissive,
  12586. transparent: transparent,
  12587. init: init,
  12588. push: push,
  12589. unshift: unshift,
  12590. finish: finish,
  12591. sort: sort
  12592. }
  12593. }
  12594. function WebGLRenderLists() {
  12595. let lists = new WeakMap()
  12596. function get(scene, renderCallDepth) {
  12597. let list
  12598. if (lists.has(scene) === false) {
  12599. list = new WebGLRenderList()
  12600. lists.set(scene, [list])
  12601. } else {
  12602. if (renderCallDepth >= lists.get(scene).length) {
  12603. list = new WebGLRenderList()
  12604. lists.get(scene).push(list)
  12605. } else {
  12606. list = lists.get(scene)[renderCallDepth]
  12607. }
  12608. }
  12609. return list
  12610. }
  12611. function dispose() {
  12612. lists = new WeakMap()
  12613. }
  12614. return {
  12615. get: get,
  12616. dispose: dispose
  12617. }
  12618. }
  12619. function UniformsCache() {
  12620. const lights = {}
  12621. return {
  12622. get: function(light) {
  12623. if (lights[light.id] !== undefined) {
  12624. return lights[light.id]
  12625. }
  12626. let uniforms
  12627. switch (light.type) {
  12628. case 'DirectionalLight':
  12629. uniforms = {
  12630. direction: new Vector3(),
  12631. color: new Color()
  12632. }
  12633. break
  12634. case 'SpotLight':
  12635. uniforms = {
  12636. position: new Vector3(),
  12637. direction: new Vector3(),
  12638. color: new Color(),
  12639. distance: 0,
  12640. coneCos: 0,
  12641. penumbraCos: 0,
  12642. decay: 0
  12643. }
  12644. break
  12645. case 'PointLight':
  12646. uniforms = {
  12647. position: new Vector3(),
  12648. color: new Color(),
  12649. distance: 0,
  12650. decay: 0
  12651. }
  12652. break
  12653. case 'HemisphereLight':
  12654. uniforms = {
  12655. direction: new Vector3(),
  12656. skyColor: new Color(),
  12657. groundColor: new Color()
  12658. }
  12659. break
  12660. case 'RectAreaLight':
  12661. uniforms = {
  12662. color: new Color(),
  12663. position: new Vector3(),
  12664. halfWidth: new Vector3(),
  12665. halfHeight: new Vector3()
  12666. }
  12667. break
  12668. }
  12669. lights[light.id] = uniforms
  12670. return uniforms
  12671. }
  12672. }
  12673. }
  12674. function ShadowUniformsCache() {
  12675. const lights = {}
  12676. return {
  12677. get: function(light) {
  12678. if (lights[light.id] !== undefined) {
  12679. return lights[light.id]
  12680. }
  12681. let uniforms
  12682. switch (light.type) {
  12683. case 'DirectionalLight':
  12684. uniforms = {
  12685. shadowBias: 0,
  12686. shadowNormalBias: 0,
  12687. shadowRadius: 1,
  12688. shadowMapSize: new Vector2()
  12689. }
  12690. break
  12691. case 'SpotLight':
  12692. uniforms = {
  12693. shadowBias: 0,
  12694. shadowNormalBias: 0,
  12695. shadowRadius: 1,
  12696. shadowMapSize: new Vector2()
  12697. }
  12698. break
  12699. case 'PointLight':
  12700. uniforms = {
  12701. shadowBias: 0,
  12702. shadowNormalBias: 0,
  12703. shadowRadius: 1,
  12704. shadowMapSize: new Vector2(),
  12705. shadowCameraNear: 1,
  12706. shadowCameraFar: 1000
  12707. }
  12708. break
  12709. // TODO (abelnation): set RectAreaLight shadow uniforms
  12710. }
  12711. lights[light.id] = uniforms
  12712. return uniforms
  12713. }
  12714. }
  12715. }
  12716. let nextVersion = 0
  12717. function shadowCastingLightsFirst(lightA, lightB) {
  12718. return (lightB.castShadow ? 1 : 0) - (lightA.castShadow ? 1 : 0)
  12719. }
  12720. function WebGLLights(extensions, capabilities) {
  12721. const cache = new UniformsCache()
  12722. const shadowCache = ShadowUniformsCache()
  12723. const state = {
  12724. version: 0,
  12725. hash: {
  12726. directionalLength: -1,
  12727. pointLength: -1,
  12728. spotLength: -1,
  12729. rectAreaLength: -1,
  12730. hemiLength: -1,
  12731. numDirectionalShadows: -1,
  12732. numPointShadows: -1,
  12733. numSpotShadows: -1
  12734. },
  12735. ambient: [0, 0, 0],
  12736. probe: [],
  12737. directional: [],
  12738. directionalShadow: [],
  12739. directionalShadowMap: [],
  12740. directionalShadowMatrix: [],
  12741. spot: [],
  12742. spotShadow: [],
  12743. spotShadowMap: [],
  12744. spotShadowMatrix: [],
  12745. rectArea: [],
  12746. rectAreaLTC1: null,
  12747. rectAreaLTC2: null,
  12748. point: [],
  12749. pointShadow: [],
  12750. pointShadowMap: [],
  12751. pointShadowMatrix: [],
  12752. hemi: []
  12753. }
  12754. for (let i = 0; i < 9; i++) state.probe.push(new Vector3())
  12755. const vector3 = new Vector3()
  12756. const matrix4 = new Matrix4()
  12757. const matrix42 = new Matrix4()
  12758. function setup(lights, physicallyCorrectLights) {
  12759. let r = 0,
  12760. g = 0,
  12761. b = 0
  12762. for (let i = 0; i < 9; i++) state.probe[i].set(0, 0, 0)
  12763. let directionalLength = 0
  12764. let pointLength = 0
  12765. let spotLength = 0
  12766. let rectAreaLength = 0
  12767. let hemiLength = 0
  12768. let numDirectionalShadows = 0
  12769. let numPointShadows = 0
  12770. let numSpotShadows = 0
  12771. lights.sort(shadowCastingLightsFirst)
  12772. // artist-friendly light intensity scaling factor
  12773. const scaleFactor = physicallyCorrectLights !== true ? Math.PI : 1
  12774. for (let i = 0, l = lights.length; i < l; i++) {
  12775. const light = lights[i]
  12776. const color = light.color
  12777. const intensity = light.intensity
  12778. const distance = light.distance
  12779. const shadowMap = light.shadow && light.shadow.map ? light.shadow.map.texture : null
  12780. if (light.isAmbientLight) {
  12781. r += color.r * intensity * scaleFactor
  12782. g += color.g * intensity * scaleFactor
  12783. b += color.b * intensity * scaleFactor
  12784. } else if (light.isLightProbe) {
  12785. for (let j = 0; j < 9; j++) {
  12786. state.probe[j].addScaledVector(light.sh.coefficients[j], intensity)
  12787. }
  12788. } else if (light.isDirectionalLight) {
  12789. const uniforms = cache.get(light)
  12790. uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor)
  12791. if (light.castShadow) {
  12792. const shadow = light.shadow
  12793. const shadowUniforms = shadowCache.get(light)
  12794. shadowUniforms.shadowBias = shadow.bias
  12795. shadowUniforms.shadowNormalBias = shadow.normalBias
  12796. shadowUniforms.shadowRadius = shadow.radius
  12797. shadowUniforms.shadowMapSize = shadow.mapSize
  12798. state.directionalShadow[directionalLength] = shadowUniforms
  12799. state.directionalShadowMap[directionalLength] = shadowMap
  12800. state.directionalShadowMatrix[directionalLength] = light.shadow.matrix
  12801. numDirectionalShadows++
  12802. }
  12803. state.directional[directionalLength] = uniforms
  12804. directionalLength++
  12805. } else if (light.isSpotLight) {
  12806. const uniforms = cache.get(light)
  12807. uniforms.position.setFromMatrixPosition(light.matrixWorld)
  12808. uniforms.color.copy(color).multiplyScalar(intensity * scaleFactor)
  12809. uniforms.distance = distance
  12810. uniforms.coneCos = Math.cos(light.angle)
  12811. uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra))
  12812. uniforms.decay = light.decay
  12813. if (light.castShadow) {
  12814. const shadow = light.shadow
  12815. const shadowUniforms = shadowCache.get(light)
  12816. shadowUniforms.shadowBias = shadow.bias
  12817. shadowUniforms.shadowNormalBias = shadow.normalBias
  12818. shadowUniforms.shadowRadius = shadow.radius
  12819. shadowUniforms.shadowMapSize = shadow.mapSize
  12820. state.spotShadow[spotLength] = shadowUniforms
  12821. state.spotShadowMap[spotLength] = shadowMap
  12822. state.spotShadowMatrix[spotLength] = light.shadow.matrix
  12823. numSpotShadows++
  12824. }
  12825. state.spot[spotLength] = uniforms
  12826. spotLength++
  12827. } else if (light.isRectAreaLight) {
  12828. const uniforms = cache.get(light)
  12829. // (a) intensity is the total visible light emitted
  12830. //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
  12831. // (b) intensity is the brightness of the light
  12832. uniforms.color.copy(color).multiplyScalar(intensity)
  12833. uniforms.halfWidth.set(light.width * 0.5, 0.0, 0.0)
  12834. uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0)
  12835. state.rectArea[rectAreaLength] = uniforms
  12836. rectAreaLength++
  12837. } else if (light.isPointLight) {
  12838. const uniforms = cache.get(light)
  12839. uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor)
  12840. uniforms.distance = light.distance
  12841. uniforms.decay = light.decay
  12842. if (light.castShadow) {
  12843. const shadow = light.shadow
  12844. const shadowUniforms = shadowCache.get(light)
  12845. shadowUniforms.shadowBias = shadow.bias
  12846. shadowUniforms.shadowNormalBias = shadow.normalBias
  12847. shadowUniforms.shadowRadius = shadow.radius
  12848. shadowUniforms.shadowMapSize = shadow.mapSize
  12849. shadowUniforms.shadowCameraNear = shadow.camera.near
  12850. shadowUniforms.shadowCameraFar = shadow.camera.far
  12851. state.pointShadow[pointLength] = shadowUniforms
  12852. state.pointShadowMap[pointLength] = shadowMap
  12853. state.pointShadowMatrix[pointLength] = light.shadow.matrix
  12854. numPointShadows++
  12855. }
  12856. state.point[pointLength] = uniforms
  12857. pointLength++
  12858. } else if (light.isHemisphereLight) {
  12859. const uniforms = cache.get(light)
  12860. uniforms.skyColor.copy(light.color).multiplyScalar(intensity * scaleFactor)
  12861. uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity * scaleFactor)
  12862. state.hemi[hemiLength] = uniforms
  12863. hemiLength++
  12864. }
  12865. }
  12866. if (rectAreaLength > 0) {
  12867. if (capabilities.isWebGL2) {
  12868. // WebGL 2
  12869. state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1
  12870. state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2
  12871. } else {
  12872. // WebGL 1
  12873. if (extensions.has('OES_texture_float_linear') === true) {
  12874. state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1
  12875. state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2
  12876. } else if (extensions.has('OES_texture_half_float_linear') === true) {
  12877. state.rectAreaLTC1 = UniformsLib.LTC_HALF_1
  12878. state.rectAreaLTC2 = UniformsLib.LTC_HALF_2
  12879. } else {
  12880. console.error('THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.')
  12881. }
  12882. }
  12883. }
  12884. state.ambient[0] = r
  12885. state.ambient[1] = g
  12886. state.ambient[2] = b
  12887. const hash = state.hash
  12888. if (
  12889. hash.directionalLength !== directionalLength ||
  12890. hash.pointLength !== pointLength ||
  12891. hash.spotLength !== spotLength ||
  12892. hash.rectAreaLength !== rectAreaLength ||
  12893. hash.hemiLength !== hemiLength ||
  12894. hash.numDirectionalShadows !== numDirectionalShadows ||
  12895. hash.numPointShadows !== numPointShadows ||
  12896. hash.numSpotShadows !== numSpotShadows
  12897. ) {
  12898. state.directional.length = directionalLength
  12899. state.spot.length = spotLength
  12900. state.rectArea.length = rectAreaLength
  12901. state.point.length = pointLength
  12902. state.hemi.length = hemiLength
  12903. state.directionalShadow.length = numDirectionalShadows
  12904. state.directionalShadowMap.length = numDirectionalShadows
  12905. state.pointShadow.length = numPointShadows
  12906. state.pointShadowMap.length = numPointShadows
  12907. state.spotShadow.length = numSpotShadows
  12908. state.spotShadowMap.length = numSpotShadows
  12909. state.directionalShadowMatrix.length = numDirectionalShadows
  12910. state.pointShadowMatrix.length = numPointShadows
  12911. state.spotShadowMatrix.length = numSpotShadows
  12912. hash.directionalLength = directionalLength
  12913. hash.pointLength = pointLength
  12914. hash.spotLength = spotLength
  12915. hash.rectAreaLength = rectAreaLength
  12916. hash.hemiLength = hemiLength
  12917. hash.numDirectionalShadows = numDirectionalShadows
  12918. hash.numPointShadows = numPointShadows
  12919. hash.numSpotShadows = numSpotShadows
  12920. state.version = nextVersion++
  12921. }
  12922. }
  12923. function setupView(lights, camera) {
  12924. let directionalLength = 0
  12925. let pointLength = 0
  12926. let spotLength = 0
  12927. let rectAreaLength = 0
  12928. let hemiLength = 0
  12929. const viewMatrix = camera.matrixWorldInverse
  12930. for (let i = 0, l = lights.length; i < l; i++) {
  12931. const light = lights[i]
  12932. if (light.isDirectionalLight) {
  12933. const uniforms = state.directional[directionalLength]
  12934. uniforms.direction.setFromMatrixPosition(light.matrixWorld)
  12935. vector3.setFromMatrixPosition(light.target.matrixWorld)
  12936. uniforms.direction.sub(vector3)
  12937. uniforms.direction.transformDirection(viewMatrix)
  12938. directionalLength++
  12939. } else if (light.isSpotLight) {
  12940. const uniforms = state.spot[spotLength]
  12941. uniforms.position.setFromMatrixPosition(light.matrixWorld)
  12942. uniforms.position.applyMatrix4(viewMatrix)
  12943. uniforms.direction.setFromMatrixPosition(light.matrixWorld)
  12944. vector3.setFromMatrixPosition(light.target.matrixWorld)
  12945. uniforms.direction.sub(vector3)
  12946. uniforms.direction.transformDirection(viewMatrix)
  12947. spotLength++
  12948. } else if (light.isRectAreaLight) {
  12949. const uniforms = state.rectArea[rectAreaLength]
  12950. uniforms.position.setFromMatrixPosition(light.matrixWorld)
  12951. uniforms.position.applyMatrix4(viewMatrix)
  12952. // extract local rotation of light to derive width/height half vectors
  12953. matrix42.identity()
  12954. matrix4.copy(light.matrixWorld)
  12955. matrix4.premultiply(viewMatrix)
  12956. matrix42.extractRotation(matrix4)
  12957. uniforms.halfWidth.set(light.width * 0.5, 0.0, 0.0)
  12958. uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0)
  12959. uniforms.halfWidth.applyMatrix4(matrix42)
  12960. uniforms.halfHeight.applyMatrix4(matrix42)
  12961. rectAreaLength++
  12962. } else if (light.isPointLight) {
  12963. const uniforms = state.point[pointLength]
  12964. uniforms.position.setFromMatrixPosition(light.matrixWorld)
  12965. uniforms.position.applyMatrix4(viewMatrix)
  12966. pointLength++
  12967. } else if (light.isHemisphereLight) {
  12968. const uniforms = state.hemi[hemiLength]
  12969. uniforms.direction.setFromMatrixPosition(light.matrixWorld)
  12970. uniforms.direction.transformDirection(viewMatrix)
  12971. hemiLength++
  12972. }
  12973. }
  12974. }
  12975. return {
  12976. setup: setup,
  12977. setupView: setupView,
  12978. state: state
  12979. }
  12980. }
  12981. function WebGLRenderState(extensions, capabilities) {
  12982. const lights = new WebGLLights(extensions, capabilities)
  12983. const lightsArray = []
  12984. const shadowsArray = []
  12985. function init() {
  12986. lightsArray.length = 0
  12987. shadowsArray.length = 0
  12988. }
  12989. function pushLight(light) {
  12990. lightsArray.push(light)
  12991. }
  12992. function pushShadow(shadowLight) {
  12993. shadowsArray.push(shadowLight)
  12994. }
  12995. function setupLights(physicallyCorrectLights) {
  12996. lights.setup(lightsArray, physicallyCorrectLights)
  12997. }
  12998. function setupLightsView(camera) {
  12999. lights.setupView(lightsArray, camera)
  13000. }
  13001. const state = {
  13002. lightsArray: lightsArray,
  13003. shadowsArray: shadowsArray,
  13004. lights: lights
  13005. }
  13006. return {
  13007. init: init,
  13008. state: state,
  13009. setupLights: setupLights,
  13010. setupLightsView: setupLightsView,
  13011. pushLight: pushLight,
  13012. pushShadow: pushShadow
  13013. }
  13014. }
  13015. function WebGLRenderStates(extensions, capabilities) {
  13016. let renderStates = new WeakMap()
  13017. function get(scene, renderCallDepth = 0) {
  13018. let renderState
  13019. if (renderStates.has(scene) === false) {
  13020. renderState = new WebGLRenderState(extensions, capabilities)
  13021. renderStates.set(scene, [renderState])
  13022. } else {
  13023. if (renderCallDepth >= renderStates.get(scene).length) {
  13024. renderState = new WebGLRenderState(extensions, capabilities)
  13025. renderStates.get(scene).push(renderState)
  13026. } else {
  13027. renderState = renderStates.get(scene)[renderCallDepth]
  13028. }
  13029. }
  13030. return renderState
  13031. }
  13032. function dispose() {
  13033. renderStates = new WeakMap()
  13034. }
  13035. return {
  13036. get: get,
  13037. dispose: dispose
  13038. }
  13039. }
  13040. class MeshDepthMaterial extends Material {
  13041. constructor(parameters) {
  13042. super()
  13043. this.isMeshDepthMaterial = true
  13044. this.type = 'MeshDepthMaterial'
  13045. this.depthPacking = BasicDepthPacking
  13046. this.map = null
  13047. this.alphaMap = null
  13048. this.displacementMap = null
  13049. this.displacementScale = 1
  13050. this.displacementBias = 0
  13051. this.wireframe = false
  13052. this.wireframeLinewidth = 1
  13053. this.setValues(parameters)
  13054. }
  13055. copy(source) {
  13056. super.copy(source)
  13057. this.depthPacking = source.depthPacking
  13058. this.map = source.map
  13059. this.alphaMap = source.alphaMap
  13060. this.displacementMap = source.displacementMap
  13061. this.displacementScale = source.displacementScale
  13062. this.displacementBias = source.displacementBias
  13063. this.wireframe = source.wireframe
  13064. this.wireframeLinewidth = source.wireframeLinewidth
  13065. return this
  13066. }
  13067. }
  13068. class MeshDistanceMaterial extends Material {
  13069. constructor(parameters) {
  13070. super()
  13071. this.isMeshDistanceMaterial = true
  13072. this.type = 'MeshDistanceMaterial'
  13073. this.referencePosition = new Vector3()
  13074. this.nearDistance = 1
  13075. this.farDistance = 1000
  13076. this.map = null
  13077. this.alphaMap = null
  13078. this.displacementMap = null
  13079. this.displacementScale = 1
  13080. this.displacementBias = 0
  13081. this.setValues(parameters)
  13082. }
  13083. copy(source) {
  13084. super.copy(source)
  13085. this.referencePosition.copy(source.referencePosition)
  13086. this.nearDistance = source.nearDistance
  13087. this.farDistance = source.farDistance
  13088. this.map = source.map
  13089. this.alphaMap = source.alphaMap
  13090. this.displacementMap = source.displacementMap
  13091. this.displacementScale = source.displacementScale
  13092. this.displacementBias = source.displacementBias
  13093. return this
  13094. }
  13095. }
  13096. const vertex = 'void main() {\n\tgl_Position = vec4( position, 1.0 );\n}'
  13097. const fragment =
  13098. 'uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}'
  13099. function WebGLShadowMap(_renderer, _objects, _capabilities) {
  13100. let _frustum = new Frustum()
  13101. const _shadowMapSize = new Vector2(),
  13102. _viewportSize = new Vector2(),
  13103. _viewport = new Vector4(),
  13104. _depthMaterial = new MeshDepthMaterial({ depthPacking: RGBADepthPacking }),
  13105. _distanceMaterial = new MeshDistanceMaterial(),
  13106. _materialCache = {},
  13107. _maxTextureSize = _capabilities.maxTextureSize
  13108. const shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide }
  13109. const shadowMaterialVertical = new ShaderMaterial({
  13110. defines: {
  13111. VSM_SAMPLES: 8
  13112. },
  13113. uniforms: {
  13114. shadow_pass: { value: null },
  13115. resolution: { value: new Vector2() },
  13116. radius: { value: 4.0 }
  13117. },
  13118. vertexShader: vertex,
  13119. fragmentShader: fragment
  13120. })
  13121. const shadowMaterialHorizontal = shadowMaterialVertical.clone()
  13122. shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1
  13123. const fullScreenTri = new BufferGeometry()
  13124. fullScreenTri.setAttribute('position', new BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3))
  13125. const fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical)
  13126. const scope = this
  13127. this.enabled = false
  13128. this.autoUpdate = true
  13129. this.needsUpdate = false
  13130. this.type = PCFShadowMap
  13131. this.render = function(lights, scene, camera) {
  13132. if (scope.enabled === false) return
  13133. if (scope.autoUpdate === false && scope.needsUpdate === false) return
  13134. if (lights.length === 0) return
  13135. const currentRenderTarget = _renderer.getRenderTarget()
  13136. const activeCubeFace = _renderer.getActiveCubeFace()
  13137. const activeMipmapLevel = _renderer.getActiveMipmapLevel()
  13138. const _state = _renderer.state
  13139. // Set GL state for depth map.
  13140. _state.setBlending(NoBlending)
  13141. _state.buffers.color.setClear(1, 1, 1, 1)
  13142. _state.buffers.depth.setTest(true)
  13143. _state.setScissorTest(false)
  13144. // render depth map
  13145. for (let i = 0, il = lights.length; i < il; i++) {
  13146. const light = lights[i]
  13147. const shadow = light.shadow
  13148. if (shadow === undefined) {
  13149. console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.')
  13150. continue
  13151. }
  13152. if (shadow.autoUpdate === false && shadow.needsUpdate === false) continue
  13153. _shadowMapSize.copy(shadow.mapSize)
  13154. const shadowFrameExtents = shadow.getFrameExtents()
  13155. _shadowMapSize.multiply(shadowFrameExtents)
  13156. _viewportSize.copy(shadow.mapSize)
  13157. if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) {
  13158. if (_shadowMapSize.x > _maxTextureSize) {
  13159. _viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x)
  13160. _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x
  13161. shadow.mapSize.x = _viewportSize.x
  13162. }
  13163. if (_shadowMapSize.y > _maxTextureSize) {
  13164. _viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y)
  13165. _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y
  13166. shadow.mapSize.y = _viewportSize.y
  13167. }
  13168. }
  13169. if (shadow.map === null && !shadow.isPointLightShadow && this.type === VSMShadowMap) {
  13170. shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y)
  13171. shadow.map.texture.name = light.name + '.shadowMap'
  13172. shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y)
  13173. shadow.camera.updateProjectionMatrix()
  13174. }
  13175. if (shadow.map === null) {
  13176. const pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }
  13177. shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars)
  13178. shadow.map.texture.name = light.name + '.shadowMap'
  13179. shadow.camera.updateProjectionMatrix()
  13180. }
  13181. _renderer.setRenderTarget(shadow.map)
  13182. _renderer.clear()
  13183. const viewportCount = shadow.getViewportCount()
  13184. for (let vp = 0; vp < viewportCount; vp++) {
  13185. const viewport = shadow.getViewport(vp)
  13186. _viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w)
  13187. _state.viewport(_viewport)
  13188. shadow.updateMatrices(light, vp)
  13189. _frustum = shadow.getFrustum()
  13190. renderObject(scene, camera, shadow.camera, light, this.type)
  13191. }
  13192. // do blur pass for VSM
  13193. if (!shadow.isPointLightShadow && this.type === VSMShadowMap) {
  13194. VSMPass(shadow, camera)
  13195. }
  13196. shadow.needsUpdate = false
  13197. }
  13198. scope.needsUpdate = false
  13199. _renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel)
  13200. }
  13201. function VSMPass(shadow, camera) {
  13202. const geometry = _objects.update(fullScreenMesh)
  13203. if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) {
  13204. shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples
  13205. shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples
  13206. shadowMaterialVertical.needsUpdate = true
  13207. shadowMaterialHorizontal.needsUpdate = true
  13208. }
  13209. // vertical pass
  13210. shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture
  13211. shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize
  13212. shadowMaterialVertical.uniforms.radius.value = shadow.radius
  13213. _renderer.setRenderTarget(shadow.mapPass)
  13214. _renderer.clear()
  13215. _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null)
  13216. // horizontal pass
  13217. shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture
  13218. shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize
  13219. shadowMaterialHorizontal.uniforms.radius.value = shadow.radius
  13220. _renderer.setRenderTarget(shadow.map)
  13221. _renderer.clear()
  13222. _renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null)
  13223. }
  13224. function getDepthMaterial(object, material, light, shadowCameraNear, shadowCameraFar, type) {
  13225. let result = null
  13226. const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial
  13227. if (customMaterial !== undefined) {
  13228. result = customMaterial
  13229. } else {
  13230. result = light.isPointLight === true ? _distanceMaterial : _depthMaterial
  13231. }
  13232. if (
  13233. (_renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0) ||
  13234. (material.displacementMap && material.displacementScale !== 0) ||
  13235. (material.alphaMap && material.alphaTest > 0)
  13236. ) {
  13237. // in this case we need a unique material instance reflecting the
  13238. // appropriate state
  13239. const keyA = result.uuid,
  13240. keyB = material.uuid
  13241. let materialsForVariant = _materialCache[keyA]
  13242. if (materialsForVariant === undefined) {
  13243. materialsForVariant = {}
  13244. _materialCache[keyA] = materialsForVariant
  13245. }
  13246. let cachedMaterial = materialsForVariant[keyB]
  13247. if (cachedMaterial === undefined) {
  13248. cachedMaterial = result.clone()
  13249. materialsForVariant[keyB] = cachedMaterial
  13250. }
  13251. result = cachedMaterial
  13252. }
  13253. result.visible = material.visible
  13254. result.wireframe = material.wireframe
  13255. if (type === VSMShadowMap) {
  13256. result.side = material.shadowSide !== null ? material.shadowSide : material.side
  13257. } else {
  13258. result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side]
  13259. }
  13260. result.alphaMap = material.alphaMap
  13261. result.alphaTest = material.alphaTest
  13262. result.clipShadows = material.clipShadows
  13263. result.clippingPlanes = material.clippingPlanes
  13264. result.clipIntersection = material.clipIntersection
  13265. result.displacementMap = material.displacementMap
  13266. result.displacementScale = material.displacementScale
  13267. result.displacementBias = material.displacementBias
  13268. result.wireframeLinewidth = material.wireframeLinewidth
  13269. result.linewidth = material.linewidth
  13270. if (light.isPointLight === true && result.isMeshDistanceMaterial === true) {
  13271. result.referencePosition.setFromMatrixPosition(light.matrixWorld)
  13272. result.nearDistance = shadowCameraNear
  13273. result.farDistance = shadowCameraFar
  13274. }
  13275. return result
  13276. }
  13277. function renderObject(object, camera, shadowCamera, light, type) {
  13278. if (object.visible === false) return
  13279. const visible = object.layers.test(camera.layers)
  13280. if (visible && (object.isMesh || object.isLine || object.isPoints)) {
  13281. if ((object.castShadow || (object.receiveShadow && type === VSMShadowMap)) && (!object.frustumCulled || _frustum.intersectsObject(object))) {
  13282. object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld)
  13283. const geometry = _objects.update(object)
  13284. const material = object.material
  13285. if (Array.isArray(material)) {
  13286. const groups = geometry.groups
  13287. for (let k = 0, kl = groups.length; k < kl; k++) {
  13288. const group = groups[k]
  13289. const groupMaterial = material[group.materialIndex]
  13290. if (groupMaterial && groupMaterial.visible) {
  13291. const depthMaterial = getDepthMaterial(object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type)
  13292. _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group)
  13293. }
  13294. }
  13295. } else if (material.visible) {
  13296. const depthMaterial = getDepthMaterial(object, material, light, shadowCamera.near, shadowCamera.far, type)
  13297. _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null)
  13298. }
  13299. }
  13300. }
  13301. const children = object.children
  13302. for (let i = 0, l = children.length; i < l; i++) {
  13303. renderObject(children[i], camera, shadowCamera, light, type)
  13304. }
  13305. }
  13306. }
  13307. function WebGLState(gl, extensions, capabilities) {
  13308. const isWebGL2 = capabilities.isWebGL2
  13309. function ColorBuffer() {
  13310. let locked = false
  13311. const color = new Vector4()
  13312. let currentColorMask = null
  13313. const currentColorClear = new Vector4(0, 0, 0, 0)
  13314. return {
  13315. setMask: function(colorMask) {
  13316. if (currentColorMask !== colorMask && !locked) {
  13317. gl.colorMask(colorMask, colorMask, colorMask, colorMask)
  13318. currentColorMask = colorMask
  13319. }
  13320. },
  13321. setLocked: function(lock) {
  13322. locked = lock
  13323. },
  13324. setClear: function(r, g, b, a, premultipliedAlpha) {
  13325. if (premultipliedAlpha === true) {
  13326. r *= a
  13327. g *= a
  13328. b *= a
  13329. }
  13330. color.set(r, g, b, a)
  13331. if (currentColorClear.equals(color) === false) {
  13332. gl.clearColor(r, g, b, a)
  13333. currentColorClear.copy(color)
  13334. }
  13335. },
  13336. reset: function() {
  13337. locked = false
  13338. currentColorMask = null
  13339. currentColorClear.set(-1, 0, 0, 0) // set to invalid state
  13340. }
  13341. }
  13342. }
  13343. function DepthBuffer() {
  13344. let locked = false
  13345. let currentDepthMask = null
  13346. let currentDepthFunc = null
  13347. let currentDepthClear = null
  13348. return {
  13349. setTest: function(depthTest) {
  13350. if (depthTest) {
  13351. enable(2929)
  13352. } else {
  13353. disable(2929)
  13354. }
  13355. },
  13356. setMask: function(depthMask) {
  13357. if (currentDepthMask !== depthMask && !locked) {
  13358. gl.depthMask(depthMask)
  13359. currentDepthMask = depthMask
  13360. }
  13361. },
  13362. setFunc: function(depthFunc) {
  13363. if (currentDepthFunc !== depthFunc) {
  13364. if (depthFunc) {
  13365. switch (depthFunc) {
  13366. case NeverDepth:
  13367. gl.depthFunc(512)
  13368. break
  13369. case AlwaysDepth:
  13370. gl.depthFunc(519)
  13371. break
  13372. case LessDepth:
  13373. gl.depthFunc(513)
  13374. break
  13375. case LessEqualDepth:
  13376. gl.depthFunc(515)
  13377. break
  13378. case EqualDepth:
  13379. gl.depthFunc(514)
  13380. break
  13381. case GreaterEqualDepth:
  13382. gl.depthFunc(518)
  13383. break
  13384. case GreaterDepth:
  13385. gl.depthFunc(516)
  13386. break
  13387. case NotEqualDepth:
  13388. gl.depthFunc(517)
  13389. break
  13390. default:
  13391. gl.depthFunc(515)
  13392. }
  13393. } else {
  13394. gl.depthFunc(515)
  13395. }
  13396. currentDepthFunc = depthFunc
  13397. }
  13398. },
  13399. setLocked: function(lock) {
  13400. locked = lock
  13401. },
  13402. setClear: function(depth) {
  13403. if (currentDepthClear !== depth) {
  13404. gl.clearDepth(depth)
  13405. currentDepthClear = depth
  13406. }
  13407. },
  13408. reset: function() {
  13409. locked = false
  13410. currentDepthMask = null
  13411. currentDepthFunc = null
  13412. currentDepthClear = null
  13413. }
  13414. }
  13415. }
  13416. function StencilBuffer() {
  13417. let locked = false
  13418. let currentStencilMask = null
  13419. let currentStencilFunc = null
  13420. let currentStencilRef = null
  13421. let currentStencilFuncMask = null
  13422. let currentStencilFail = null
  13423. let currentStencilZFail = null
  13424. let currentStencilZPass = null
  13425. let currentStencilClear = null
  13426. return {
  13427. setTest: function(stencilTest) {
  13428. if (!locked) {
  13429. if (stencilTest) {
  13430. enable(2960)
  13431. } else {
  13432. disable(2960)
  13433. }
  13434. }
  13435. },
  13436. setMask: function(stencilMask) {
  13437. if (currentStencilMask !== stencilMask && !locked) {
  13438. gl.stencilMask(stencilMask)
  13439. currentStencilMask = stencilMask
  13440. }
  13441. },
  13442. setFunc: function(stencilFunc, stencilRef, stencilMask) {
  13443. if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) {
  13444. gl.stencilFunc(stencilFunc, stencilRef, stencilMask)
  13445. currentStencilFunc = stencilFunc
  13446. currentStencilRef = stencilRef
  13447. currentStencilFuncMask = stencilMask
  13448. }
  13449. },
  13450. setOp: function(stencilFail, stencilZFail, stencilZPass) {
  13451. if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) {
  13452. gl.stencilOp(stencilFail, stencilZFail, stencilZPass)
  13453. currentStencilFail = stencilFail
  13454. currentStencilZFail = stencilZFail
  13455. currentStencilZPass = stencilZPass
  13456. }
  13457. },
  13458. setLocked: function(lock) {
  13459. locked = lock
  13460. },
  13461. setClear: function(stencil) {
  13462. if (currentStencilClear !== stencil) {
  13463. gl.clearStencil(stencil)
  13464. currentStencilClear = stencil
  13465. }
  13466. },
  13467. reset: function() {
  13468. locked = false
  13469. currentStencilMask = null
  13470. currentStencilFunc = null
  13471. currentStencilRef = null
  13472. currentStencilFuncMask = null
  13473. currentStencilFail = null
  13474. currentStencilZFail = null
  13475. currentStencilZPass = null
  13476. currentStencilClear = null
  13477. }
  13478. }
  13479. }
  13480. //
  13481. const colorBuffer = new ColorBuffer()
  13482. const depthBuffer = new DepthBuffer()
  13483. const stencilBuffer = new StencilBuffer()
  13484. let enabledCapabilities = {}
  13485. let currentBoundFramebuffers = {}
  13486. let currentDrawbuffers = new WeakMap()
  13487. let defaultDrawbuffers = []
  13488. let currentProgram = null
  13489. let currentBlendingEnabled = false
  13490. let currentBlending = null
  13491. let currentBlendEquation = null
  13492. let currentBlendSrc = null
  13493. let currentBlendDst = null
  13494. let currentBlendEquationAlpha = null
  13495. let currentBlendSrcAlpha = null
  13496. let currentBlendDstAlpha = null
  13497. let currentPremultipledAlpha = false
  13498. let currentFlipSided = null
  13499. let currentCullFace = null
  13500. let currentLineWidth = null
  13501. let currentPolygonOffsetFactor = null
  13502. let currentPolygonOffsetUnits = null
  13503. const maxTextures = gl.getParameter(35661)
  13504. let lineWidthAvailable = false
  13505. let version = 0
  13506. const glVersion = gl.getParameter(7938)
  13507. if (glVersion.indexOf('WebGL') !== -1) {
  13508. version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1])
  13509. lineWidthAvailable = version >= 1.0
  13510. } else if (glVersion.indexOf('OpenGL ES') !== -1) {
  13511. version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1])
  13512. lineWidthAvailable = version >= 2.0
  13513. }
  13514. let currentTextureSlot = null
  13515. let currentBoundTextures = {}
  13516. const scissorParam = gl.getParameter(3088)
  13517. const viewportParam = gl.getParameter(2978)
  13518. const currentScissor = new Vector4().fromArray(scissorParam)
  13519. const currentViewport = new Vector4().fromArray(viewportParam)
  13520. function createTexture(type, target, count) {
  13521. const data = new Uint8Array(4) // 4 is required to match default unpack alignment of 4.
  13522. const texture = gl.createTexture()
  13523. gl.bindTexture(type, texture)
  13524. gl.texParameteri(type, 10241, 9728)
  13525. gl.texParameteri(type, 10240, 9728)
  13526. for (let i = 0; i < count; i++) {
  13527. gl.texImage2D(target + i, 0, 6408, 1, 1, 0, 6408, 5121, data)
  13528. }
  13529. return texture
  13530. }
  13531. const emptyTextures = {}
  13532. emptyTextures[3553] = createTexture(3553, 3553, 1)
  13533. emptyTextures[34067] = createTexture(34067, 34069, 6)
  13534. // init
  13535. colorBuffer.setClear(0, 0, 0, 1)
  13536. depthBuffer.setClear(1)
  13537. stencilBuffer.setClear(0)
  13538. enable(2929)
  13539. depthBuffer.setFunc(LessEqualDepth)
  13540. setFlipSided(false)
  13541. setCullFace(CullFaceBack)
  13542. enable(2884)
  13543. setBlending(NoBlending)
  13544. //
  13545. function enable(id) {
  13546. if (enabledCapabilities[id] !== true) {
  13547. gl.enable(id)
  13548. enabledCapabilities[id] = true
  13549. }
  13550. }
  13551. function disable(id) {
  13552. if (enabledCapabilities[id] !== false) {
  13553. gl.disable(id)
  13554. enabledCapabilities[id] = false
  13555. }
  13556. }
  13557. function bindFramebuffer(target, framebuffer) {
  13558. if (currentBoundFramebuffers[target] !== framebuffer) {
  13559. gl.bindFramebuffer(target, framebuffer)
  13560. currentBoundFramebuffers[target] = framebuffer
  13561. if (isWebGL2) {
  13562. // 36009 is equivalent to 36160
  13563. if (target === 36009) {
  13564. currentBoundFramebuffers[36160] = framebuffer
  13565. }
  13566. if (target === 36160) {
  13567. currentBoundFramebuffers[36009] = framebuffer
  13568. }
  13569. }
  13570. return true
  13571. }
  13572. return false
  13573. }
  13574. function drawBuffers(renderTarget, framebuffer) {
  13575. let drawBuffers = defaultDrawbuffers
  13576. let needsUpdate = false
  13577. if (renderTarget) {
  13578. drawBuffers = currentDrawbuffers.get(framebuffer)
  13579. if (drawBuffers === undefined) {
  13580. drawBuffers = []
  13581. currentDrawbuffers.set(framebuffer, drawBuffers)
  13582. }
  13583. if (renderTarget.isWebGLMultipleRenderTargets) {
  13584. const textures = renderTarget.texture
  13585. if (drawBuffers.length !== textures.length || drawBuffers[0] !== 36064) {
  13586. for (let i = 0, il = textures.length; i < il; i++) {
  13587. drawBuffers[i] = 36064 + i
  13588. }
  13589. drawBuffers.length = textures.length
  13590. needsUpdate = true
  13591. }
  13592. } else {
  13593. if (drawBuffers[0] !== 36064) {
  13594. drawBuffers[0] = 36064
  13595. needsUpdate = true
  13596. }
  13597. }
  13598. } else {
  13599. if (drawBuffers[0] !== 1029) {
  13600. drawBuffers[0] = 1029
  13601. needsUpdate = true
  13602. }
  13603. }
  13604. if (needsUpdate) {
  13605. if (capabilities.isWebGL2) {
  13606. gl.drawBuffers(drawBuffers)
  13607. } else {
  13608. extensions.get('WEBGL_draw_buffers').drawBuffersWEBGL(drawBuffers)
  13609. }
  13610. }
  13611. }
  13612. function useProgram(program) {
  13613. if (currentProgram !== program) {
  13614. gl.useProgram(program)
  13615. currentProgram = program
  13616. return true
  13617. }
  13618. return false
  13619. }
  13620. const equationToGL = {
  13621. [AddEquation]: 32774,
  13622. [SubtractEquation]: 32778,
  13623. [ReverseSubtractEquation]: 32779
  13624. }
  13625. if (isWebGL2) {
  13626. equationToGL[MinEquation] = 32775
  13627. equationToGL[MaxEquation] = 32776
  13628. } else {
  13629. const extension = extensions.get('EXT_blend_minmax')
  13630. if (extension !== null) {
  13631. equationToGL[MinEquation] = extension.MIN_EXT
  13632. equationToGL[MaxEquation] = extension.MAX_EXT
  13633. }
  13634. }
  13635. const factorToGL = {
  13636. [ZeroFactor]: 0,
  13637. [OneFactor]: 1,
  13638. [SrcColorFactor]: 768,
  13639. [SrcAlphaFactor]: 770,
  13640. [SrcAlphaSaturateFactor]: 776,
  13641. [DstColorFactor]: 774,
  13642. [DstAlphaFactor]: 772,
  13643. [OneMinusSrcColorFactor]: 769,
  13644. [OneMinusSrcAlphaFactor]: 771,
  13645. [OneMinusDstColorFactor]: 775,
  13646. [OneMinusDstAlphaFactor]: 773
  13647. }
  13648. function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) {
  13649. if (blending === NoBlending) {
  13650. if (currentBlendingEnabled === true) {
  13651. disable(3042)
  13652. currentBlendingEnabled = false
  13653. }
  13654. return
  13655. }
  13656. if (currentBlendingEnabled === false) {
  13657. enable(3042)
  13658. currentBlendingEnabled = true
  13659. }
  13660. if (blending !== CustomBlending) {
  13661. if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) {
  13662. if (currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation) {
  13663. gl.blendEquation(32774)
  13664. currentBlendEquation = AddEquation
  13665. currentBlendEquationAlpha = AddEquation
  13666. }
  13667. if (premultipliedAlpha) {
  13668. switch (blending) {
  13669. case NormalBlending:
  13670. gl.blendFuncSeparate(1, 771, 1, 771)
  13671. break
  13672. case AdditiveBlending:
  13673. gl.blendFunc(1, 1)
  13674. break
  13675. case SubtractiveBlending:
  13676. gl.blendFuncSeparate(0, 769, 0, 1)
  13677. break
  13678. case MultiplyBlending:
  13679. gl.blendFuncSeparate(0, 768, 0, 770)
  13680. break
  13681. default:
  13682. console.error('THREE.WebGLState: Invalid blending: ', blending)
  13683. break
  13684. }
  13685. } else {
  13686. switch (blending) {
  13687. case NormalBlending:
  13688. gl.blendFuncSeparate(770, 771, 1, 771)
  13689. break
  13690. case AdditiveBlending:
  13691. gl.blendFunc(770, 1)
  13692. break
  13693. case SubtractiveBlending:
  13694. gl.blendFuncSeparate(0, 769, 0, 1)
  13695. break
  13696. case MultiplyBlending:
  13697. gl.blendFunc(0, 768)
  13698. break
  13699. default:
  13700. console.error('THREE.WebGLState: Invalid blending: ', blending)
  13701. break
  13702. }
  13703. }
  13704. currentBlendSrc = null
  13705. currentBlendDst = null
  13706. currentBlendSrcAlpha = null
  13707. currentBlendDstAlpha = null
  13708. currentBlending = blending
  13709. currentPremultipledAlpha = premultipliedAlpha
  13710. }
  13711. return
  13712. }
  13713. // custom blending
  13714. blendEquationAlpha = blendEquationAlpha || blendEquation
  13715. blendSrcAlpha = blendSrcAlpha || blendSrc
  13716. blendDstAlpha = blendDstAlpha || blendDst
  13717. if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) {
  13718. gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha])
  13719. currentBlendEquation = blendEquation
  13720. currentBlendEquationAlpha = blendEquationAlpha
  13721. }
  13722. if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) {
  13723. gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha])
  13724. currentBlendSrc = blendSrc
  13725. currentBlendDst = blendDst
  13726. currentBlendSrcAlpha = blendSrcAlpha
  13727. currentBlendDstAlpha = blendDstAlpha
  13728. }
  13729. currentBlending = blending
  13730. currentPremultipledAlpha = null
  13731. }
  13732. function setMaterial(material, frontFaceCW) {
  13733. material.side === DoubleSide ? disable(2884) : enable(2884)
  13734. let flipSided = material.side === BackSide
  13735. if (frontFaceCW) flipSided = !flipSided
  13736. setFlipSided(flipSided)
  13737. material.blending === NormalBlending && material.transparent === false
  13738. ? setBlending(NoBlending)
  13739. : setBlending(
  13740. material.blending,
  13741. material.blendEquation,
  13742. material.blendSrc,
  13743. material.blendDst,
  13744. material.blendEquationAlpha,
  13745. material.blendSrcAlpha,
  13746. material.blendDstAlpha,
  13747. material.premultipliedAlpha
  13748. )
  13749. depthBuffer.setFunc(material.depthFunc)
  13750. depthBuffer.setTest(material.depthTest)
  13751. depthBuffer.setMask(material.depthWrite)
  13752. colorBuffer.setMask(material.colorWrite)
  13753. const stencilWrite = material.stencilWrite
  13754. stencilBuffer.setTest(stencilWrite)
  13755. if (stencilWrite) {
  13756. stencilBuffer.setMask(material.stencilWriteMask)
  13757. stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask)
  13758. stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass)
  13759. }
  13760. setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits)
  13761. material.alphaToCoverage === true ? enable(32926) : disable(32926)
  13762. }
  13763. //
  13764. function setFlipSided(flipSided) {
  13765. if (currentFlipSided !== flipSided) {
  13766. if (flipSided) {
  13767. gl.frontFace(2304)
  13768. } else {
  13769. gl.frontFace(2305)
  13770. }
  13771. currentFlipSided = flipSided
  13772. }
  13773. }
  13774. function setCullFace(cullFace) {
  13775. if (cullFace !== CullFaceNone) {
  13776. enable(2884)
  13777. if (cullFace !== currentCullFace) {
  13778. if (cullFace === CullFaceBack) {
  13779. gl.cullFace(1029)
  13780. } else if (cullFace === CullFaceFront) {
  13781. gl.cullFace(1028)
  13782. } else {
  13783. gl.cullFace(1032)
  13784. }
  13785. }
  13786. } else {
  13787. disable(2884)
  13788. }
  13789. currentCullFace = cullFace
  13790. }
  13791. function setLineWidth(width) {
  13792. if (width !== currentLineWidth) {
  13793. if (lineWidthAvailable) gl.lineWidth(width)
  13794. currentLineWidth = width
  13795. }
  13796. }
  13797. function setPolygonOffset(polygonOffset, factor, units) {
  13798. if (polygonOffset) {
  13799. enable(32823)
  13800. if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) {
  13801. gl.polygonOffset(factor, units)
  13802. currentPolygonOffsetFactor = factor
  13803. currentPolygonOffsetUnits = units
  13804. }
  13805. } else {
  13806. disable(32823)
  13807. }
  13808. }
  13809. function setScissorTest(scissorTest) {
  13810. if (scissorTest) {
  13811. enable(3089)
  13812. } else {
  13813. disable(3089)
  13814. }
  13815. }
  13816. // texture
  13817. function activeTexture(webglSlot) {
  13818. if (webglSlot === undefined) webglSlot = 33984 + maxTextures - 1
  13819. if (currentTextureSlot !== webglSlot) {
  13820. gl.activeTexture(webglSlot)
  13821. currentTextureSlot = webglSlot
  13822. }
  13823. }
  13824. function bindTexture(webglType, webglTexture) {
  13825. if (currentTextureSlot === null) {
  13826. activeTexture()
  13827. }
  13828. let boundTexture = currentBoundTextures[currentTextureSlot]
  13829. if (boundTexture === undefined) {
  13830. boundTexture = { type: undefined, texture: undefined }
  13831. currentBoundTextures[currentTextureSlot] = boundTexture
  13832. }
  13833. if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
  13834. gl.bindTexture(webglType, webglTexture || emptyTextures[webglType])
  13835. boundTexture.type = webglType
  13836. boundTexture.texture = webglTexture
  13837. }
  13838. }
  13839. function unbindTexture() {
  13840. const boundTexture = currentBoundTextures[currentTextureSlot]
  13841. if (boundTexture !== undefined && boundTexture.type !== undefined) {
  13842. gl.bindTexture(boundTexture.type, null)
  13843. boundTexture.type = undefined
  13844. boundTexture.texture = undefined
  13845. }
  13846. }
  13847. function compressedTexImage2D() {
  13848. try {
  13849. gl.compressedTexImage2D.apply(gl, arguments)
  13850. } catch (error) {
  13851. console.error('THREE.WebGLState:', error)
  13852. }
  13853. }
  13854. function texSubImage2D() {
  13855. try {
  13856. gl.texSubImage2D.apply(gl, arguments)
  13857. } catch (error) {
  13858. console.error('THREE.WebGLState:', error)
  13859. }
  13860. }
  13861. function texSubImage3D() {
  13862. try {
  13863. gl.texSubImage3D.apply(gl, arguments)
  13864. } catch (error) {
  13865. console.error('THREE.WebGLState:', error)
  13866. }
  13867. }
  13868. function compressedTexSubImage2D() {
  13869. try {
  13870. gl.compressedTexSubImage2D.apply(gl, arguments)
  13871. } catch (error) {
  13872. console.error('THREE.WebGLState:', error)
  13873. }
  13874. }
  13875. function texStorage2D() {
  13876. try {
  13877. gl.texStorage2D.apply(gl, arguments)
  13878. } catch (error) {
  13879. console.error('THREE.WebGLState:', error)
  13880. }
  13881. }
  13882. function texStorage3D() {
  13883. try {
  13884. gl.texStorage3D.apply(gl, arguments)
  13885. } catch (error) {
  13886. console.error('THREE.WebGLState:', error)
  13887. }
  13888. }
  13889. function texImage2D() {
  13890. try {
  13891. gl.texImage2D.apply(gl, arguments)
  13892. } catch (error) {
  13893. console.error('THREE.WebGLState:', error)
  13894. }
  13895. }
  13896. function texImage3D() {
  13897. try {
  13898. gl.texImage3D.apply(gl, arguments)
  13899. } catch (error) {
  13900. console.error('THREE.WebGLState:', error)
  13901. }
  13902. }
  13903. //
  13904. function scissor(scissor) {
  13905. if (currentScissor.equals(scissor) === false) {
  13906. gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w)
  13907. currentScissor.copy(scissor)
  13908. }
  13909. }
  13910. function viewport(viewport) {
  13911. if (currentViewport.equals(viewport) === false) {
  13912. gl.viewport(viewport.x, viewport.y, viewport.z, viewport.w)
  13913. currentViewport.copy(viewport)
  13914. }
  13915. }
  13916. //
  13917. function reset() {
  13918. // reset state
  13919. gl.disable(3042)
  13920. gl.disable(2884)
  13921. gl.disable(2929)
  13922. gl.disable(32823)
  13923. gl.disable(3089)
  13924. gl.disable(2960)
  13925. gl.disable(32926)
  13926. gl.blendEquation(32774)
  13927. gl.blendFunc(1, 0)
  13928. gl.blendFuncSeparate(1, 0, 1, 0)
  13929. gl.colorMask(true, true, true, true)
  13930. gl.clearColor(0, 0, 0, 0)
  13931. gl.depthMask(true)
  13932. gl.depthFunc(513)
  13933. gl.clearDepth(1)
  13934. gl.stencilMask(0xffffffff)
  13935. gl.stencilFunc(519, 0, 0xffffffff)
  13936. gl.stencilOp(7680, 7680, 7680)
  13937. gl.clearStencil(0)
  13938. gl.cullFace(1029)
  13939. gl.frontFace(2305)
  13940. gl.polygonOffset(0, 0)
  13941. gl.activeTexture(33984)
  13942. gl.bindFramebuffer(36160, null)
  13943. if (isWebGL2 === true) {
  13944. gl.bindFramebuffer(36009, null)
  13945. gl.bindFramebuffer(36008, null)
  13946. }
  13947. gl.useProgram(null)
  13948. gl.lineWidth(1)
  13949. gl.scissor(0, 0, gl.canvas.width, gl.canvas.height)
  13950. gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
  13951. // reset internals
  13952. enabledCapabilities = {}
  13953. currentTextureSlot = null
  13954. currentBoundTextures = {}
  13955. currentBoundFramebuffers = {}
  13956. currentDrawbuffers = new WeakMap()
  13957. defaultDrawbuffers = []
  13958. currentProgram = null
  13959. currentBlendingEnabled = false
  13960. currentBlending = null
  13961. currentBlendEquation = null
  13962. currentBlendSrc = null
  13963. currentBlendDst = null
  13964. currentBlendEquationAlpha = null
  13965. currentBlendSrcAlpha = null
  13966. currentBlendDstAlpha = null
  13967. currentPremultipledAlpha = false
  13968. currentFlipSided = null
  13969. currentCullFace = null
  13970. currentLineWidth = null
  13971. currentPolygonOffsetFactor = null
  13972. currentPolygonOffsetUnits = null
  13973. currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height)
  13974. currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height)
  13975. colorBuffer.reset()
  13976. depthBuffer.reset()
  13977. stencilBuffer.reset()
  13978. }
  13979. return {
  13980. buffers: {
  13981. color: colorBuffer,
  13982. depth: depthBuffer,
  13983. stencil: stencilBuffer
  13984. },
  13985. enable: enable,
  13986. disable: disable,
  13987. bindFramebuffer: bindFramebuffer,
  13988. drawBuffers: drawBuffers,
  13989. useProgram: useProgram,
  13990. setBlending: setBlending,
  13991. setMaterial: setMaterial,
  13992. setFlipSided: setFlipSided,
  13993. setCullFace: setCullFace,
  13994. setLineWidth: setLineWidth,
  13995. setPolygonOffset: setPolygonOffset,
  13996. setScissorTest: setScissorTest,
  13997. activeTexture: activeTexture,
  13998. bindTexture: bindTexture,
  13999. unbindTexture: unbindTexture,
  14000. compressedTexImage2D: compressedTexImage2D,
  14001. texImage2D: texImage2D,
  14002. texImage3D: texImage3D,
  14003. texStorage2D: texStorage2D,
  14004. texStorage3D: texStorage3D,
  14005. texSubImage2D: texSubImage2D,
  14006. texSubImage3D: texSubImage3D,
  14007. compressedTexSubImage2D: compressedTexSubImage2D,
  14008. scissor: scissor,
  14009. viewport: viewport,
  14010. reset: reset
  14011. }
  14012. }
  14013. function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info) {
  14014. const isWebGL2 = capabilities.isWebGL2
  14015. const maxTextures = capabilities.maxTextures
  14016. const maxCubemapSize = capabilities.maxCubemapSize
  14017. const maxTextureSize = capabilities.maxTextureSize
  14018. const maxSamples = capabilities.maxSamples
  14019. const multisampledRTTExt = extensions.has('WEBGL_multisampled_render_to_texture') ? extensions.get('WEBGL_multisampled_render_to_texture') : null
  14020. const supportsInvalidateFramebuffer = /OculusBrowser/g.test(navigator.userAgent)
  14021. const _videoTextures = new WeakMap()
  14022. let _canvas
  14023. const _sources = new WeakMap() // maps WebglTexture objects to instances of Source
  14024. // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
  14025. // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
  14026. // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
  14027. let useOffscreenCanvas = false
  14028. try {
  14029. useOffscreenCanvas =
  14030. typeof OffscreenCanvas !== 'undefined' &&
  14031. // eslint-disable-next-line compat/compat
  14032. new OffscreenCanvas(1, 1).getContext('2d') !== null
  14033. } catch (err) {
  14034. // Ignore any errors
  14035. }
  14036. function createCanvas(width, height) {
  14037. // Use OffscreenCanvas when available. Specially needed in web workers
  14038. return useOffscreenCanvas
  14039. ? // eslint-disable-next-line compat/compat
  14040. new OffscreenCanvas(width, height)
  14041. : createElementNS('canvas')
  14042. }
  14043. function resizeImage(image, needsPowerOfTwo, needsNewCanvas, maxSize) {
  14044. let scale = 1
  14045. // handle case if texture exceeds max size
  14046. if (image.width > maxSize || image.height > maxSize) {
  14047. scale = maxSize / Math.max(image.width, image.height)
  14048. }
  14049. // only perform resize if necessary
  14050. if (scale < 1 || needsPowerOfTwo === true) {
  14051. // only perform resize for certain image types
  14052. if (
  14053. (typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
  14054. (typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
  14055. (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)
  14056. ) {
  14057. const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor
  14058. const width = floor(scale * image.width)
  14059. const height = floor(scale * image.height)
  14060. if (_canvas === undefined) _canvas = createCanvas(width, height)
  14061. // cube textures can't reuse the same canvas
  14062. const canvas = needsNewCanvas ? createCanvas(width, height) : _canvas
  14063. canvas.width = width
  14064. canvas.height = height
  14065. const context = canvas.getContext('2d')
  14066. context.drawImage(image, 0, 0, width, height)
  14067. console.warn('THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').')
  14068. return canvas
  14069. } else {
  14070. if ('data' in image) {
  14071. console.warn('THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').')
  14072. }
  14073. return image
  14074. }
  14075. }
  14076. return image
  14077. }
  14078. function isPowerOfTwo$1(image) {
  14079. return isPowerOfTwo(image.width) && isPowerOfTwo(image.height)
  14080. }
  14081. function textureNeedsPowerOfTwo(texture) {
  14082. if (isWebGL2) return false
  14083. return texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping || (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter)
  14084. }
  14085. function textureNeedsGenerateMipmaps(texture, supportsMips) {
  14086. return texture.generateMipmaps && supportsMips && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter
  14087. }
  14088. function generateMipmap(target) {
  14089. _gl.generateMipmap(target)
  14090. }
  14091. function getInternalFormat(internalFormatName, glFormat, glType, encoding, isVideoTexture = false) {
  14092. if (isWebGL2 === false) return glFormat
  14093. if (internalFormatName !== null) {
  14094. if (_gl[internalFormatName] !== undefined) return _gl[internalFormatName]
  14095. console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '" + internalFormatName + "'")
  14096. }
  14097. let internalFormat = glFormat
  14098. if (glFormat === 6403) {
  14099. if (glType === 5126) internalFormat = 33326
  14100. if (glType === 5131) internalFormat = 33325
  14101. if (glType === 5121) internalFormat = 33321
  14102. }
  14103. if (glFormat === 33319) {
  14104. if (glType === 5126) internalFormat = 33328
  14105. if (glType === 5131) internalFormat = 33327
  14106. if (glType === 5121) internalFormat = 33323
  14107. }
  14108. if (glFormat === 6408) {
  14109. if (glType === 5126) internalFormat = 34836
  14110. if (glType === 5131) internalFormat = 34842
  14111. if (glType === 5121) internalFormat = encoding === sRGBEncoding && isVideoTexture === false ? 35907 : 32856
  14112. if (glType === 32819) internalFormat = 32854
  14113. if (glType === 32820) internalFormat = 32855
  14114. }
  14115. if (internalFormat === 33325 || internalFormat === 33326 || internalFormat === 33327 || internalFormat === 33328 || internalFormat === 34842 || internalFormat === 34836) {
  14116. extensions.get('EXT_color_buffer_float')
  14117. }
  14118. return internalFormat
  14119. }
  14120. function getMipLevels(texture, image, supportsMips) {
  14121. if (textureNeedsGenerateMipmaps(texture, supportsMips) === true || (texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter)) {
  14122. return Math.log2(Math.max(image.width, image.height)) + 1
  14123. } else if (texture.mipmaps !== undefined && texture.mipmaps.length > 0) {
  14124. // user-defined mipmaps
  14125. return texture.mipmaps.length
  14126. } else if (texture.isCompressedTexture && Array.isArray(texture.image)) {
  14127. return image.mipmaps.length
  14128. } else {
  14129. // texture without mipmaps (only base level)
  14130. return 1
  14131. }
  14132. }
  14133. // Fallback filters for non-power-of-2 textures
  14134. function filterFallback(f) {
  14135. if (f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter) {
  14136. return 9728
  14137. }
  14138. return 9729
  14139. }
  14140. //
  14141. function onTextureDispose(event) {
  14142. const texture = event.target
  14143. texture.removeEventListener('dispose', onTextureDispose)
  14144. deallocateTexture(texture)
  14145. if (texture.isVideoTexture) {
  14146. _videoTextures.delete(texture)
  14147. }
  14148. }
  14149. function onRenderTargetDispose(event) {
  14150. const renderTarget = event.target
  14151. renderTarget.removeEventListener('dispose', onRenderTargetDispose)
  14152. deallocateRenderTarget(renderTarget)
  14153. }
  14154. //
  14155. function deallocateTexture(texture) {
  14156. const textureProperties = properties.get(texture)
  14157. if (textureProperties.__webglInit === undefined) return
  14158. // check if it's necessary to remove the WebGLTexture object
  14159. const source = texture.source
  14160. const webglTextures = _sources.get(source)
  14161. if (webglTextures) {
  14162. const webglTexture = webglTextures[textureProperties.__cacheKey]
  14163. webglTexture.usedTimes--
  14164. // the WebGLTexture object is not used anymore, remove it
  14165. if (webglTexture.usedTimes === 0) {
  14166. deleteTexture(texture)
  14167. }
  14168. // remove the weak map entry if no WebGLTexture uses the source anymore
  14169. if (Object.keys(webglTextures).length === 0) {
  14170. _sources.delete(source)
  14171. }
  14172. }
  14173. properties.remove(texture)
  14174. }
  14175. function deleteTexture(texture) {
  14176. const textureProperties = properties.get(texture)
  14177. _gl.deleteTexture(textureProperties.__webglTexture)
  14178. const source = texture.source
  14179. const webglTextures = _sources.get(source)
  14180. delete webglTextures[textureProperties.__cacheKey]
  14181. info.memory.textures--
  14182. }
  14183. function deallocateRenderTarget(renderTarget) {
  14184. const texture = renderTarget.texture
  14185. const renderTargetProperties = properties.get(renderTarget)
  14186. const textureProperties = properties.get(texture)
  14187. if (textureProperties.__webglTexture !== undefined) {
  14188. _gl.deleteTexture(textureProperties.__webglTexture)
  14189. info.memory.textures--
  14190. }
  14191. if (renderTarget.depthTexture) {
  14192. renderTarget.depthTexture.dispose()
  14193. }
  14194. if (renderTarget.isWebGLCubeRenderTarget) {
  14195. for (let i = 0; i < 6; i++) {
  14196. _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i])
  14197. if (renderTargetProperties.__webglDepthbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i])
  14198. }
  14199. } else {
  14200. _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer)
  14201. if (renderTargetProperties.__webglDepthbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer)
  14202. if (renderTargetProperties.__webglMultisampledFramebuffer) _gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer)
  14203. if (renderTargetProperties.__webglColorRenderbuffer) {
  14204. for (let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i++) {
  14205. if (renderTargetProperties.__webglColorRenderbuffer[i]) _gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer[i])
  14206. }
  14207. }
  14208. if (renderTargetProperties.__webglDepthRenderbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer)
  14209. }
  14210. if (renderTarget.isWebGLMultipleRenderTargets) {
  14211. for (let i = 0, il = texture.length; i < il; i++) {
  14212. const attachmentProperties = properties.get(texture[i])
  14213. if (attachmentProperties.__webglTexture) {
  14214. _gl.deleteTexture(attachmentProperties.__webglTexture)
  14215. info.memory.textures--
  14216. }
  14217. properties.remove(texture[i])
  14218. }
  14219. }
  14220. properties.remove(texture)
  14221. properties.remove(renderTarget)
  14222. }
  14223. //
  14224. let textureUnits = 0
  14225. function resetTextureUnits() {
  14226. textureUnits = 0
  14227. }
  14228. function allocateTextureUnit() {
  14229. const textureUnit = textureUnits
  14230. if (textureUnit >= maxTextures) {
  14231. console.warn('THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures)
  14232. }
  14233. textureUnits += 1
  14234. return textureUnit
  14235. }
  14236. function getTextureCacheKey(texture) {
  14237. const array = []
  14238. array.push(texture.wrapS)
  14239. array.push(texture.wrapT)
  14240. array.push(texture.magFilter)
  14241. array.push(texture.minFilter)
  14242. array.push(texture.anisotropy)
  14243. array.push(texture.internalFormat)
  14244. array.push(texture.format)
  14245. array.push(texture.type)
  14246. array.push(texture.generateMipmaps)
  14247. array.push(texture.premultiplyAlpha)
  14248. array.push(texture.flipY)
  14249. array.push(texture.unpackAlignment)
  14250. array.push(texture.encoding)
  14251. return array.join()
  14252. }
  14253. //
  14254. function setTexture2D(texture, slot) {
  14255. const textureProperties = properties.get(texture)
  14256. if (texture.isVideoTexture) updateVideoTexture(texture)
  14257. if (texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version) {
  14258. const image = texture.image
  14259. if (image === null) {
  14260. console.warn('THREE.WebGLRenderer: Texture marked for update but no image data found.')
  14261. } else if (image.complete === false) {
  14262. console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete')
  14263. } else {
  14264. uploadTexture(textureProperties, texture, slot)
  14265. return
  14266. }
  14267. }
  14268. state.activeTexture(33984 + slot)
  14269. state.bindTexture(3553, textureProperties.__webglTexture)
  14270. }
  14271. function setTexture2DArray(texture, slot) {
  14272. const textureProperties = properties.get(texture)
  14273. if (texture.version > 0 && textureProperties.__version !== texture.version) {
  14274. uploadTexture(textureProperties, texture, slot)
  14275. return
  14276. }
  14277. state.activeTexture(33984 + slot)
  14278. state.bindTexture(35866, textureProperties.__webglTexture)
  14279. }
  14280. function setTexture3D(texture, slot) {
  14281. const textureProperties = properties.get(texture)
  14282. if (texture.version > 0 && textureProperties.__version !== texture.version) {
  14283. uploadTexture(textureProperties, texture, slot)
  14284. return
  14285. }
  14286. state.activeTexture(33984 + slot)
  14287. state.bindTexture(32879, textureProperties.__webglTexture)
  14288. }
  14289. function setTextureCube(texture, slot) {
  14290. const textureProperties = properties.get(texture)
  14291. if (texture.version > 0 && textureProperties.__version !== texture.version) {
  14292. uploadCubeTexture(textureProperties, texture, slot)
  14293. return
  14294. }
  14295. state.activeTexture(33984 + slot)
  14296. state.bindTexture(34067, textureProperties.__webglTexture)
  14297. }
  14298. const wrappingToGL = {
  14299. [RepeatWrapping]: 10497,
  14300. [ClampToEdgeWrapping]: 33071,
  14301. [MirroredRepeatWrapping]: 33648
  14302. }
  14303. const filterToGL = {
  14304. [NearestFilter]: 9728,
  14305. [NearestMipmapNearestFilter]: 9984,
  14306. [NearestMipmapLinearFilter]: 9986,
  14307. [LinearFilter]: 9729,
  14308. [LinearMipmapNearestFilter]: 9985,
  14309. [LinearMipmapLinearFilter]: 9987
  14310. }
  14311. function setTextureParameters(textureType, texture, supportsMips) {
  14312. if (supportsMips) {
  14313. _gl.texParameteri(textureType, 10242, wrappingToGL[texture.wrapS])
  14314. _gl.texParameteri(textureType, 10243, wrappingToGL[texture.wrapT])
  14315. if (textureType === 32879 || textureType === 35866) {
  14316. _gl.texParameteri(textureType, 32882, wrappingToGL[texture.wrapR])
  14317. }
  14318. _gl.texParameteri(textureType, 10240, filterToGL[texture.magFilter])
  14319. _gl.texParameteri(textureType, 10241, filterToGL[texture.minFilter])
  14320. } else {
  14321. _gl.texParameteri(textureType, 10242, 33071)
  14322. _gl.texParameteri(textureType, 10243, 33071)
  14323. if (textureType === 32879 || textureType === 35866) {
  14324. _gl.texParameteri(textureType, 32882, 33071)
  14325. }
  14326. if (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) {
  14327. console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.')
  14328. }
  14329. _gl.texParameteri(textureType, 10240, filterFallback(texture.magFilter))
  14330. _gl.texParameteri(textureType, 10241, filterFallback(texture.minFilter))
  14331. if (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) {
  14332. console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.')
  14333. }
  14334. }
  14335. if (extensions.has('EXT_texture_filter_anisotropic') === true) {
  14336. const extension = extensions.get('EXT_texture_filter_anisotropic')
  14337. if (texture.type === FloatType && extensions.has('OES_texture_float_linear') === false) return // verify extension for WebGL 1 and WebGL 2
  14338. if (isWebGL2 === false && texture.type === HalfFloatType && extensions.has('OES_texture_half_float_linear') === false) return // verify extension for WebGL 1 only
  14339. if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) {
  14340. _gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy()))
  14341. properties.get(texture).__currentAnisotropy = texture.anisotropy
  14342. }
  14343. }
  14344. }
  14345. function initTexture(textureProperties, texture) {
  14346. let forceUpload = false
  14347. if (textureProperties.__webglInit === undefined) {
  14348. textureProperties.__webglInit = true
  14349. texture.addEventListener('dispose', onTextureDispose)
  14350. }
  14351. // create Source <-> WebGLTextures mapping if necessary
  14352. const source = texture.source
  14353. let webglTextures = _sources.get(source)
  14354. if (webglTextures === undefined) {
  14355. webglTextures = {}
  14356. _sources.set(source, webglTextures)
  14357. }
  14358. // check if there is already a WebGLTexture object for the given texture parameters
  14359. const textureCacheKey = getTextureCacheKey(texture)
  14360. if (textureCacheKey !== textureProperties.__cacheKey) {
  14361. // if not, create a new instance of WebGLTexture
  14362. if (webglTextures[textureCacheKey] === undefined) {
  14363. // create new entry
  14364. webglTextures[textureCacheKey] = {
  14365. texture: _gl.createTexture(),
  14366. usedTimes: 0
  14367. }
  14368. info.memory.textures++
  14369. // when a new instance of WebGLTexture was created, a texture upload is required
  14370. // even if the image contents are identical
  14371. forceUpload = true
  14372. }
  14373. webglTextures[textureCacheKey].usedTimes++
  14374. // every time the texture cache key changes, it's necessary to check if an instance of
  14375. // WebGLTexture can be deleted in order to avoid a memory leak.
  14376. const webglTexture = webglTextures[textureProperties.__cacheKey]
  14377. if (webglTexture !== undefined) {
  14378. webglTextures[textureProperties.__cacheKey].usedTimes--
  14379. if (webglTexture.usedTimes === 0) {
  14380. deleteTexture(texture)
  14381. }
  14382. }
  14383. // store references to cache key and WebGLTexture object
  14384. textureProperties.__cacheKey = textureCacheKey
  14385. textureProperties.__webglTexture = webglTextures[textureCacheKey].texture
  14386. }
  14387. return forceUpload
  14388. }
  14389. function uploadTexture(textureProperties, texture, slot) {
  14390. let textureType = 3553
  14391. if (texture.isDataArrayTexture) textureType = 35866
  14392. if (texture.isData3DTexture) textureType = 32879
  14393. const forceUpload = initTexture(textureProperties, texture)
  14394. const source = texture.source
  14395. state.activeTexture(33984 + slot)
  14396. state.bindTexture(textureType, textureProperties.__webglTexture)
  14397. if (source.version !== source.__currentVersion || forceUpload === true) {
  14398. _gl.pixelStorei(37440, texture.flipY)
  14399. _gl.pixelStorei(37441, texture.premultiplyAlpha)
  14400. _gl.pixelStorei(3317, texture.unpackAlignment)
  14401. _gl.pixelStorei(37443, 0)
  14402. const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false
  14403. let image = resizeImage(texture.image, needsPowerOfTwo, false, maxTextureSize)
  14404. image = verifyColorSpace(texture, image)
  14405. const supportsMips = isPowerOfTwo$1(image) || isWebGL2,
  14406. glFormat = utils.convert(texture.format, texture.encoding)
  14407. let glType = utils.convert(texture.type),
  14408. glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture)
  14409. setTextureParameters(textureType, texture, supportsMips)
  14410. let mipmap
  14411. const mipmaps = texture.mipmaps
  14412. const useTexStorage = isWebGL2 && texture.isVideoTexture !== true
  14413. const allocateMemory = source.__currentVersion === undefined || forceUpload === true
  14414. const levels = getMipLevels(texture, image, supportsMips)
  14415. if (texture.isDepthTexture) {
  14416. // populate depth texture with dummy data
  14417. glInternalFormat = 6402
  14418. if (isWebGL2) {
  14419. if (texture.type === FloatType) {
  14420. glInternalFormat = 36012
  14421. } else if (texture.type === UnsignedIntType) {
  14422. glInternalFormat = 33190
  14423. } else if (texture.type === UnsignedInt248Type) {
  14424. glInternalFormat = 35056
  14425. } else {
  14426. glInternalFormat = 33189 // WebGL2 requires sized internalformat for glTexImage2D
  14427. }
  14428. } else {
  14429. if (texture.type === FloatType) {
  14430. console.error('WebGLRenderer: Floating point depth texture requires WebGL2.')
  14431. }
  14432. }
  14433. // validation checks for WebGL 1
  14434. if (texture.format === DepthFormat && glInternalFormat === 6402) {
  14435. // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  14436. // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
  14437. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  14438. if (texture.type !== UnsignedShortType && texture.type !== UnsignedIntType) {
  14439. console.warn('THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.')
  14440. texture.type = UnsignedIntType
  14441. glType = utils.convert(texture.type)
  14442. }
  14443. }
  14444. if (texture.format === DepthStencilFormat && glInternalFormat === 6402) {
  14445. // Depth stencil textures need the DEPTH_STENCIL internal format
  14446. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  14447. glInternalFormat = 34041
  14448. // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
  14449. // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
  14450. // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
  14451. if (texture.type !== UnsignedInt248Type) {
  14452. console.warn('THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.')
  14453. texture.type = UnsignedInt248Type
  14454. glType = utils.convert(texture.type)
  14455. }
  14456. }
  14457. //
  14458. if (allocateMemory) {
  14459. if (useTexStorage) {
  14460. state.texStorage2D(3553, 1, glInternalFormat, image.width, image.height)
  14461. } else {
  14462. state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null)
  14463. }
  14464. }
  14465. } else if (texture.isDataTexture) {
  14466. // use manually created mipmaps if available
  14467. // if there are no manual mipmaps
  14468. // set 0 level mipmap and then use GL to generate other mipmap levels
  14469. if (mipmaps.length > 0 && supportsMips) {
  14470. if (useTexStorage && allocateMemory) {
  14471. state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height)
  14472. }
  14473. for (let i = 0, il = mipmaps.length; i < il; i++) {
  14474. mipmap = mipmaps[i]
  14475. if (useTexStorage) {
  14476. state.texSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data)
  14477. } else {
  14478. state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data)
  14479. }
  14480. }
  14481. texture.generateMipmaps = false
  14482. } else {
  14483. if (useTexStorage) {
  14484. if (allocateMemory) {
  14485. state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height)
  14486. }
  14487. state.texSubImage2D(3553, 0, 0, 0, image.width, image.height, glFormat, glType, image.data)
  14488. } else {
  14489. state.texImage2D(3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data)
  14490. }
  14491. }
  14492. } else if (texture.isCompressedTexture) {
  14493. if (useTexStorage && allocateMemory) {
  14494. state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height)
  14495. }
  14496. for (let i = 0, il = mipmaps.length; i < il; i++) {
  14497. mipmap = mipmaps[i]
  14498. if (texture.format !== RGBAFormat) {
  14499. if (glFormat !== null) {
  14500. if (useTexStorage) {
  14501. state.compressedTexSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data)
  14502. } else {
  14503. state.compressedTexImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data)
  14504. }
  14505. } else {
  14506. console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()')
  14507. }
  14508. } else {
  14509. if (useTexStorage) {
  14510. state.texSubImage2D(3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data)
  14511. } else {
  14512. state.texImage2D(3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data)
  14513. }
  14514. }
  14515. }
  14516. } else if (texture.isDataArrayTexture) {
  14517. if (useTexStorage) {
  14518. if (allocateMemory) {
  14519. state.texStorage3D(35866, levels, glInternalFormat, image.width, image.height, image.depth)
  14520. }
  14521. state.texSubImage3D(35866, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data)
  14522. } else {
  14523. state.texImage3D(35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data)
  14524. }
  14525. } else if (texture.isData3DTexture) {
  14526. if (useTexStorage) {
  14527. if (allocateMemory) {
  14528. state.texStorage3D(32879, levels, glInternalFormat, image.width, image.height, image.depth)
  14529. }
  14530. state.texSubImage3D(32879, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data)
  14531. } else {
  14532. state.texImage3D(32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data)
  14533. }
  14534. } else if (texture.isFramebufferTexture) {
  14535. if (allocateMemory) {
  14536. if (useTexStorage) {
  14537. state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height)
  14538. } else {
  14539. let width = image.width,
  14540. height = image.height
  14541. for (let i = 0; i < levels; i++) {
  14542. state.texImage2D(3553, i, glInternalFormat, width, height, 0, glFormat, glType, null)
  14543. width >>= 1
  14544. height >>= 1
  14545. }
  14546. }
  14547. }
  14548. } else {
  14549. // regular Texture (image, video, canvas)
  14550. // use manually created mipmaps if available
  14551. // if there are no manual mipmaps
  14552. // set 0 level mipmap and then use GL to generate other mipmap levels
  14553. if (mipmaps.length > 0 && supportsMips) {
  14554. if (useTexStorage && allocateMemory) {
  14555. state.texStorage2D(3553, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height)
  14556. }
  14557. for (let i = 0, il = mipmaps.length; i < il; i++) {
  14558. mipmap = mipmaps[i]
  14559. if (useTexStorage) {
  14560. state.texSubImage2D(3553, i, 0, 0, glFormat, glType, mipmap)
  14561. } else {
  14562. state.texImage2D(3553, i, glInternalFormat, glFormat, glType, mipmap)
  14563. }
  14564. }
  14565. texture.generateMipmaps = false
  14566. } else {
  14567. if (useTexStorage) {
  14568. if (allocateMemory) {
  14569. state.texStorage2D(3553, levels, glInternalFormat, image.width, image.height)
  14570. }
  14571. state.texSubImage2D(3553, 0, 0, 0, glFormat, glType, image)
  14572. } else {
  14573. state.texImage2D(3553, 0, glInternalFormat, glFormat, glType, image)
  14574. }
  14575. }
  14576. }
  14577. if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
  14578. generateMipmap(textureType)
  14579. }
  14580. source.__currentVersion = source.version
  14581. if (texture.onUpdate) texture.onUpdate(texture)
  14582. }
  14583. textureProperties.__version = texture.version
  14584. }
  14585. function uploadCubeTexture(textureProperties, texture, slot) {
  14586. if (texture.image.length !== 6) return
  14587. const forceUpload = initTexture(textureProperties, texture)
  14588. const source = texture.source
  14589. state.activeTexture(33984 + slot)
  14590. state.bindTexture(34067, textureProperties.__webglTexture)
  14591. if (source.version !== source.__currentVersion || forceUpload === true) {
  14592. _gl.pixelStorei(37440, texture.flipY)
  14593. _gl.pixelStorei(37441, texture.premultiplyAlpha)
  14594. _gl.pixelStorei(3317, texture.unpackAlignment)
  14595. _gl.pixelStorei(37443, 0)
  14596. const isCompressed = texture.isCompressedTexture || texture.image[0].isCompressedTexture
  14597. const isDataTexture = texture.image[0] && texture.image[0].isDataTexture
  14598. const cubeImage = []
  14599. for (let i = 0; i < 6; i++) {
  14600. if (!isCompressed && !isDataTexture) {
  14601. cubeImage[i] = resizeImage(texture.image[i], false, true, maxCubemapSize)
  14602. } else {
  14603. cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i]
  14604. }
  14605. cubeImage[i] = verifyColorSpace(texture, cubeImage[i])
  14606. }
  14607. const image = cubeImage[0],
  14608. supportsMips = isPowerOfTwo$1(image) || isWebGL2,
  14609. glFormat = utils.convert(texture.format, texture.encoding),
  14610. glType = utils.convert(texture.type),
  14611. glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding)
  14612. const useTexStorage = isWebGL2 && texture.isVideoTexture !== true
  14613. const allocateMemory = source.__currentVersion === undefined || forceUpload === true
  14614. let levels = getMipLevels(texture, image, supportsMips)
  14615. setTextureParameters(34067, texture, supportsMips)
  14616. let mipmaps
  14617. if (isCompressed) {
  14618. if (useTexStorage && allocateMemory) {
  14619. state.texStorage2D(34067, levels, glInternalFormat, image.width, image.height)
  14620. }
  14621. for (let i = 0; i < 6; i++) {
  14622. mipmaps = cubeImage[i].mipmaps
  14623. for (let j = 0; j < mipmaps.length; j++) {
  14624. const mipmap = mipmaps[j]
  14625. if (texture.format !== RGBAFormat) {
  14626. if (glFormat !== null) {
  14627. if (useTexStorage) {
  14628. state.compressedTexSubImage2D(34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data)
  14629. } else {
  14630. state.compressedTexImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data)
  14631. }
  14632. } else {
  14633. console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()')
  14634. }
  14635. } else {
  14636. if (useTexStorage) {
  14637. state.texSubImage2D(34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data)
  14638. } else {
  14639. state.texImage2D(34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data)
  14640. }
  14641. }
  14642. }
  14643. }
  14644. } else {
  14645. mipmaps = texture.mipmaps
  14646. if (useTexStorage && allocateMemory) {
  14647. // TODO: Uniformly handle mipmap definitions
  14648. // Normal textures and compressed cube textures define base level + mips with their mipmap array
  14649. // Uncompressed cube textures use their mipmap array only for mips (no base level)
  14650. if (mipmaps.length > 0) levels++
  14651. state.texStorage2D(34067, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height)
  14652. }
  14653. for (let i = 0; i < 6; i++) {
  14654. if (isDataTexture) {
  14655. if (useTexStorage) {
  14656. state.texSubImage2D(34069 + i, 0, 0, 0, cubeImage[i].width, cubeImage[i].height, glFormat, glType, cubeImage[i].data)
  14657. } else {
  14658. state.texImage2D(34069 + i, 0, glInternalFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data)
  14659. }
  14660. for (let j = 0; j < mipmaps.length; j++) {
  14661. const mipmap = mipmaps[j]
  14662. const mipmapImage = mipmap.image[i].image
  14663. if (useTexStorage) {
  14664. state.texSubImage2D(34069 + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data)
  14665. } else {
  14666. state.texImage2D(34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data)
  14667. }
  14668. }
  14669. } else {
  14670. if (useTexStorage) {
  14671. state.texSubImage2D(34069 + i, 0, 0, 0, glFormat, glType, cubeImage[i])
  14672. } else {
  14673. state.texImage2D(34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[i])
  14674. }
  14675. for (let j = 0; j < mipmaps.length; j++) {
  14676. const mipmap = mipmaps[j]
  14677. if (useTexStorage) {
  14678. state.texSubImage2D(34069 + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i])
  14679. } else {
  14680. state.texImage2D(34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i])
  14681. }
  14682. }
  14683. }
  14684. }
  14685. }
  14686. if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
  14687. // We assume images for cube map have the same size.
  14688. generateMipmap(34067)
  14689. }
  14690. source.__currentVersion = source.version
  14691. if (texture.onUpdate) texture.onUpdate(texture)
  14692. }
  14693. textureProperties.__version = texture.version
  14694. }
  14695. // Render targets
  14696. // Setup storage for target texture and bind it to correct framebuffer
  14697. function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget) {
  14698. const glFormat = utils.convert(texture.format, texture.encoding)
  14699. const glType = utils.convert(texture.type)
  14700. const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding)
  14701. const renderTargetProperties = properties.get(renderTarget)
  14702. if (!renderTargetProperties.__hasExternalTextures) {
  14703. if (textureTarget === 32879 || textureTarget === 35866) {
  14704. state.texImage3D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null)
  14705. } else {
  14706. state.texImage2D(textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null)
  14707. }
  14708. }
  14709. state.bindFramebuffer(36160, framebuffer)
  14710. if (useMultisampledRTT(renderTarget)) {
  14711. multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget))
  14712. } else {
  14713. _gl.framebufferTexture2D(36160, attachment, textureTarget, properties.get(texture).__webglTexture, 0)
  14714. }
  14715. state.bindFramebuffer(36160, null)
  14716. }
  14717. // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
  14718. function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) {
  14719. _gl.bindRenderbuffer(36161, renderbuffer)
  14720. if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) {
  14721. let glInternalFormat = 33189
  14722. if (isMultisample || useMultisampledRTT(renderTarget)) {
  14723. const depthTexture = renderTarget.depthTexture
  14724. if (depthTexture && depthTexture.isDepthTexture) {
  14725. if (depthTexture.type === FloatType) {
  14726. glInternalFormat = 36012
  14727. } else if (depthTexture.type === UnsignedIntType) {
  14728. glInternalFormat = 33190
  14729. }
  14730. }
  14731. const samples = getRenderTargetSamples(renderTarget)
  14732. if (useMultisampledRTT(renderTarget)) {
  14733. multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height)
  14734. } else {
  14735. _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height)
  14736. }
  14737. } else {
  14738. _gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height)
  14739. }
  14740. _gl.framebufferRenderbuffer(36160, 36096, 36161, renderbuffer)
  14741. } else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) {
  14742. const samples = getRenderTargetSamples(renderTarget)
  14743. if (isMultisample && useMultisampledRTT(renderTarget) === false) {
  14744. _gl.renderbufferStorageMultisample(36161, samples, 35056, renderTarget.width, renderTarget.height)
  14745. } else if (useMultisampledRTT(renderTarget)) {
  14746. multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, 35056, renderTarget.width, renderTarget.height)
  14747. } else {
  14748. _gl.renderbufferStorage(36161, 34041, renderTarget.width, renderTarget.height)
  14749. }
  14750. _gl.framebufferRenderbuffer(36160, 33306, 36161, renderbuffer)
  14751. } else {
  14752. const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]
  14753. for (let i = 0; i < textures.length; i++) {
  14754. const texture = textures[i]
  14755. const glFormat = utils.convert(texture.format, texture.encoding)
  14756. const glType = utils.convert(texture.type)
  14757. const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding)
  14758. const samples = getRenderTargetSamples(renderTarget)
  14759. if (isMultisample && useMultisampledRTT(renderTarget) === false) {
  14760. _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height)
  14761. } else if (useMultisampledRTT(renderTarget)) {
  14762. multisampledRTTExt.renderbufferStorageMultisampleEXT(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height)
  14763. } else {
  14764. _gl.renderbufferStorage(36161, glInternalFormat, renderTarget.width, renderTarget.height)
  14765. }
  14766. }
  14767. }
  14768. _gl.bindRenderbuffer(36161, null)
  14769. }
  14770. // Setup resources for a Depth Texture for a FBO (needs an extension)
  14771. function setupDepthTexture(framebuffer, renderTarget) {
  14772. const isCube = renderTarget && renderTarget.isWebGLCubeRenderTarget
  14773. if (isCube) throw new Error('Depth Texture with cube render targets is not supported')
  14774. state.bindFramebuffer(36160, framebuffer)
  14775. if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) {
  14776. throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture')
  14777. }
  14778. // upload an empty depth texture with framebuffer size
  14779. if (
  14780. !properties.get(renderTarget.depthTexture).__webglTexture ||
  14781. renderTarget.depthTexture.image.width !== renderTarget.width ||
  14782. renderTarget.depthTexture.image.height !== renderTarget.height
  14783. ) {
  14784. renderTarget.depthTexture.image.width = renderTarget.width
  14785. renderTarget.depthTexture.image.height = renderTarget.height
  14786. renderTarget.depthTexture.needsUpdate = true
  14787. }
  14788. setTexture2D(renderTarget.depthTexture, 0)
  14789. const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture
  14790. const samples = getRenderTargetSamples(renderTarget)
  14791. if (renderTarget.depthTexture.format === DepthFormat) {
  14792. if (useMultisampledRTT(renderTarget)) {
  14793. multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, 36096, 3553, webglDepthTexture, 0, samples)
  14794. } else {
  14795. _gl.framebufferTexture2D(36160, 36096, 3553, webglDepthTexture, 0)
  14796. }
  14797. } else if (renderTarget.depthTexture.format === DepthStencilFormat) {
  14798. if (useMultisampledRTT(renderTarget)) {
  14799. multisampledRTTExt.framebufferTexture2DMultisampleEXT(36160, 33306, 3553, webglDepthTexture, 0, samples)
  14800. } else {
  14801. _gl.framebufferTexture2D(36160, 33306, 3553, webglDepthTexture, 0)
  14802. }
  14803. } else {
  14804. throw new Error('Unknown depthTexture format')
  14805. }
  14806. }
  14807. // Setup GL resources for a non-texture depth buffer
  14808. function setupDepthRenderbuffer(renderTarget) {
  14809. const renderTargetProperties = properties.get(renderTarget)
  14810. const isCube = renderTarget.isWebGLCubeRenderTarget === true
  14811. if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) {
  14812. if (isCube) throw new Error('target.depthTexture not supported in Cube render targets')
  14813. setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget)
  14814. } else {
  14815. if (isCube) {
  14816. renderTargetProperties.__webglDepthbuffer = []
  14817. for (let i = 0; i < 6; i++) {
  14818. state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer[i])
  14819. renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer()
  14820. setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget, false)
  14821. }
  14822. } else {
  14823. state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer)
  14824. renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer()
  14825. setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget, false)
  14826. }
  14827. }
  14828. state.bindFramebuffer(36160, null)
  14829. }
  14830. // rebind framebuffer with external textures
  14831. function rebindTextures(renderTarget, colorTexture, depthTexture) {
  14832. const renderTargetProperties = properties.get(renderTarget)
  14833. if (colorTexture !== undefined) {
  14834. setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553)
  14835. }
  14836. if (depthTexture !== undefined) {
  14837. setupDepthRenderbuffer(renderTarget)
  14838. }
  14839. }
  14840. // Set up GL resources for the render target
  14841. function setupRenderTarget(renderTarget) {
  14842. const texture = renderTarget.texture
  14843. const renderTargetProperties = properties.get(renderTarget)
  14844. const textureProperties = properties.get(texture)
  14845. renderTarget.addEventListener('dispose', onRenderTargetDispose)
  14846. if (renderTarget.isWebGLMultipleRenderTargets !== true) {
  14847. if (textureProperties.__webglTexture === undefined) {
  14848. textureProperties.__webglTexture = _gl.createTexture()
  14849. }
  14850. textureProperties.__version = texture.version
  14851. info.memory.textures++
  14852. }
  14853. const isCube = renderTarget.isWebGLCubeRenderTarget === true
  14854. const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true
  14855. const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2
  14856. // Setup framebuffer
  14857. if (isCube) {
  14858. renderTargetProperties.__webglFramebuffer = []
  14859. for (let i = 0; i < 6; i++) {
  14860. renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer()
  14861. }
  14862. } else {
  14863. renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer()
  14864. if (isMultipleRenderTargets) {
  14865. if (capabilities.drawBuffers) {
  14866. const textures = renderTarget.texture
  14867. for (let i = 0, il = textures.length; i < il; i++) {
  14868. const attachmentProperties = properties.get(textures[i])
  14869. if (attachmentProperties.__webglTexture === undefined) {
  14870. attachmentProperties.__webglTexture = _gl.createTexture()
  14871. info.memory.textures++
  14872. }
  14873. }
  14874. } else {
  14875. console.warn('THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.')
  14876. }
  14877. }
  14878. if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) {
  14879. const textures = isMultipleRenderTargets ? texture : [texture]
  14880. renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer()
  14881. renderTargetProperties.__webglColorRenderbuffer = []
  14882. state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer)
  14883. for (let i = 0; i < textures.length; i++) {
  14884. const texture = textures[i]
  14885. renderTargetProperties.__webglColorRenderbuffer[i] = _gl.createRenderbuffer()
  14886. _gl.bindRenderbuffer(36161, renderTargetProperties.__webglColorRenderbuffer[i])
  14887. const glFormat = utils.convert(texture.format, texture.encoding)
  14888. const glType = utils.convert(texture.type)
  14889. const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.encoding)
  14890. const samples = getRenderTargetSamples(renderTarget)
  14891. _gl.renderbufferStorageMultisample(36161, samples, glInternalFormat, renderTarget.width, renderTarget.height)
  14892. _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[i])
  14893. }
  14894. _gl.bindRenderbuffer(36161, null)
  14895. if (renderTarget.depthBuffer) {
  14896. renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer()
  14897. setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true)
  14898. }
  14899. state.bindFramebuffer(36160, null)
  14900. }
  14901. }
  14902. // Setup color buffer
  14903. if (isCube) {
  14904. state.bindTexture(34067, textureProperties.__webglTexture)
  14905. setTextureParameters(34067, texture, supportsMips)
  14906. for (let i = 0; i < 6; i++) {
  14907. setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, 36064, 34069 + i)
  14908. }
  14909. if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
  14910. generateMipmap(34067)
  14911. }
  14912. state.unbindTexture()
  14913. } else if (isMultipleRenderTargets) {
  14914. const textures = renderTarget.texture
  14915. for (let i = 0, il = textures.length; i < il; i++) {
  14916. const attachment = textures[i]
  14917. const attachmentProperties = properties.get(attachment)
  14918. state.bindTexture(3553, attachmentProperties.__webglTexture)
  14919. setTextureParameters(3553, attachment, supportsMips)
  14920. setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553)
  14921. if (textureNeedsGenerateMipmaps(attachment, supportsMips)) {
  14922. generateMipmap(3553)
  14923. }
  14924. }
  14925. state.unbindTexture()
  14926. } else {
  14927. let glTextureType = 3553
  14928. if (renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget) {
  14929. if (isWebGL2) {
  14930. glTextureType = renderTarget.isWebGL3DRenderTarget ? 32879 : 35866
  14931. } else {
  14932. console.error('THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.')
  14933. }
  14934. }
  14935. state.bindTexture(glTextureType, textureProperties.__webglTexture)
  14936. setTextureParameters(glTextureType, texture, supportsMips)
  14937. setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType)
  14938. if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
  14939. generateMipmap(glTextureType)
  14940. }
  14941. state.unbindTexture()
  14942. }
  14943. // Setup depth and stencil buffers
  14944. if (renderTarget.depthBuffer) {
  14945. setupDepthRenderbuffer(renderTarget)
  14946. }
  14947. }
  14948. function updateRenderTargetMipmap(renderTarget) {
  14949. const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2
  14950. const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture]
  14951. for (let i = 0, il = textures.length; i < il; i++) {
  14952. const texture = textures[i]
  14953. if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
  14954. const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553
  14955. const webglTexture = properties.get(texture).__webglTexture
  14956. state.bindTexture(target, webglTexture)
  14957. generateMipmap(target)
  14958. state.unbindTexture()
  14959. }
  14960. }
  14961. }
  14962. function updateMultisampleRenderTarget(renderTarget) {
  14963. if (isWebGL2 && renderTarget.samples > 0 && useMultisampledRTT(renderTarget) === false) {
  14964. const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [renderTarget.texture]
  14965. const width = renderTarget.width
  14966. const height = renderTarget.height
  14967. let mask = 16384
  14968. const invalidationArray = []
  14969. const depthStyle = renderTarget.stencilBuffer ? 33306 : 36096
  14970. const renderTargetProperties = properties.get(renderTarget)
  14971. const isMultipleRenderTargets = renderTarget.isWebGLMultipleRenderTargets === true
  14972. // If MRT we need to remove FBO attachments
  14973. if (isMultipleRenderTargets) {
  14974. for (let i = 0; i < textures.length; i++) {
  14975. state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer)
  14976. _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, null)
  14977. state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer)
  14978. _gl.framebufferTexture2D(36009, 36064 + i, 3553, null, 0)
  14979. }
  14980. }
  14981. state.bindFramebuffer(36008, renderTargetProperties.__webglMultisampledFramebuffer)
  14982. state.bindFramebuffer(36009, renderTargetProperties.__webglFramebuffer)
  14983. for (let i = 0; i < textures.length; i++) {
  14984. invalidationArray.push(36064 + i)
  14985. if (renderTarget.depthBuffer) {
  14986. invalidationArray.push(depthStyle)
  14987. }
  14988. const ignoreDepthValues = renderTargetProperties.__ignoreDepthValues !== undefined ? renderTargetProperties.__ignoreDepthValues : false
  14989. if (ignoreDepthValues === false) {
  14990. if (renderTarget.depthBuffer) mask |= 256
  14991. if (renderTarget.stencilBuffer) mask |= 1024
  14992. }
  14993. if (isMultipleRenderTargets) {
  14994. _gl.framebufferRenderbuffer(36008, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer[i])
  14995. }
  14996. if (ignoreDepthValues === true) {
  14997. _gl.invalidateFramebuffer(36008, [depthStyle])
  14998. _gl.invalidateFramebuffer(36009, [depthStyle])
  14999. }
  15000. if (isMultipleRenderTargets) {
  15001. const webglTexture = properties.get(textures[i]).__webglTexture
  15002. _gl.framebufferTexture2D(36009, 36064, 3553, webglTexture, 0)
  15003. }
  15004. _gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, 9728)
  15005. if (supportsInvalidateFramebuffer) {
  15006. _gl.invalidateFramebuffer(36008, invalidationArray)
  15007. }
  15008. }
  15009. state.bindFramebuffer(36008, null)
  15010. state.bindFramebuffer(36009, null)
  15011. // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments
  15012. if (isMultipleRenderTargets) {
  15013. for (let i = 0; i < textures.length; i++) {
  15014. state.bindFramebuffer(36160, renderTargetProperties.__webglMultisampledFramebuffer)
  15015. _gl.framebufferRenderbuffer(36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[i])
  15016. const webglTexture = properties.get(textures[i]).__webglTexture
  15017. state.bindFramebuffer(36160, renderTargetProperties.__webglFramebuffer)
  15018. _gl.framebufferTexture2D(36009, 36064 + i, 3553, webglTexture, 0)
  15019. }
  15020. }
  15021. state.bindFramebuffer(36009, renderTargetProperties.__webglMultisampledFramebuffer)
  15022. }
  15023. }
  15024. function getRenderTargetSamples(renderTarget) {
  15025. return Math.min(maxSamples, renderTarget.samples)
  15026. }
  15027. function useMultisampledRTT(renderTarget) {
  15028. const renderTargetProperties = properties.get(renderTarget)
  15029. return isWebGL2 && renderTarget.samples > 0 && extensions.has('WEBGL_multisampled_render_to_texture') === true && renderTargetProperties.__useRenderToTexture !== false
  15030. }
  15031. function updateVideoTexture(texture) {
  15032. const frame = info.render.frame
  15033. // Check the last frame we updated the VideoTexture
  15034. if (_videoTextures.get(texture) !== frame) {
  15035. _videoTextures.set(texture, frame)
  15036. texture.update()
  15037. }
  15038. }
  15039. function verifyColorSpace(texture, image) {
  15040. const encoding = texture.encoding
  15041. const format = texture.format
  15042. const type = texture.type
  15043. if (texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat) return image
  15044. if (encoding !== LinearEncoding) {
  15045. // sRGB
  15046. if (encoding === sRGBEncoding) {
  15047. if (isWebGL2 === false) {
  15048. // in WebGL 1, try to use EXT_sRGB extension and unsized formats
  15049. if (extensions.has('EXT_sRGB') === true && format === RGBAFormat) {
  15050. texture.format = _SRGBAFormat
  15051. // it's not possible to generate mips in WebGL 1 with this extension
  15052. texture.minFilter = LinearFilter
  15053. texture.generateMipmaps = false
  15054. } else {
  15055. // slow fallback (CPU decode)
  15056. image = ImageUtils.sRGBToLinear(image)
  15057. }
  15058. } else {
  15059. // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format
  15060. if (format !== RGBAFormat || type !== UnsignedByteType) {
  15061. console.warn('THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.')
  15062. }
  15063. }
  15064. } else {
  15065. console.error('THREE.WebGLTextures: Unsupported texture encoding:', encoding)
  15066. }
  15067. }
  15068. return image
  15069. }
  15070. //
  15071. this.allocateTextureUnit = allocateTextureUnit
  15072. this.resetTextureUnits = resetTextureUnits
  15073. this.setTexture2D = setTexture2D
  15074. this.setTexture2DArray = setTexture2DArray
  15075. this.setTexture3D = setTexture3D
  15076. this.setTextureCube = setTextureCube
  15077. this.rebindTextures = rebindTextures
  15078. this.setupRenderTarget = setupRenderTarget
  15079. this.updateRenderTargetMipmap = updateRenderTargetMipmap
  15080. this.updateMultisampleRenderTarget = updateMultisampleRenderTarget
  15081. this.setupDepthRenderbuffer = setupDepthRenderbuffer
  15082. this.setupFrameBufferTexture = setupFrameBufferTexture
  15083. this.useMultisampledRTT = useMultisampledRTT
  15084. }
  15085. function WebGLUtils(gl, extensions, capabilities) {
  15086. const isWebGL2 = capabilities.isWebGL2
  15087. function convert(p, encoding = null) {
  15088. let extension
  15089. if (p === UnsignedByteType) return 5121
  15090. if (p === UnsignedShort4444Type) return 32819
  15091. if (p === UnsignedShort5551Type) return 32820
  15092. if (p === ByteType) return 5120
  15093. if (p === ShortType) return 5122
  15094. if (p === UnsignedShortType) return 5123
  15095. if (p === IntType) return 5124
  15096. if (p === UnsignedIntType) return 5125
  15097. if (p === FloatType) return 5126
  15098. if (p === HalfFloatType) {
  15099. if (isWebGL2) return 5131
  15100. extension = extensions.get('OES_texture_half_float')
  15101. if (extension !== null) {
  15102. return extension.HALF_FLOAT_OES
  15103. } else {
  15104. return null
  15105. }
  15106. }
  15107. if (p === AlphaFormat) return 6406
  15108. if (p === RGBAFormat) return 6408
  15109. if (p === LuminanceFormat) return 6409
  15110. if (p === LuminanceAlphaFormat) return 6410
  15111. if (p === DepthFormat) return 6402
  15112. if (p === DepthStencilFormat) return 34041
  15113. if (p === RedFormat) return 6403
  15114. if (p === RGBFormat) {
  15115. console.warn('THREE.WebGLRenderer: THREE.RGBFormat has been removed. Use THREE.RGBAFormat instead. https://github.com/mrdoob/three.js/pull/23228')
  15116. return 6408
  15117. }
  15118. // WebGL 1 sRGB fallback
  15119. if (p === _SRGBAFormat) {
  15120. extension = extensions.get('EXT_sRGB')
  15121. if (extension !== null) {
  15122. return extension.SRGB_ALPHA_EXT
  15123. } else {
  15124. return null
  15125. }
  15126. }
  15127. // WebGL2 formats.
  15128. if (p === RedIntegerFormat) return 36244
  15129. if (p === RGFormat) return 33319
  15130. if (p === RGIntegerFormat) return 33320
  15131. if (p === RGBAIntegerFormat) return 36249
  15132. // S3TC
  15133. if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
  15134. if (encoding === sRGBEncoding) {
  15135. extension = extensions.get('WEBGL_compressed_texture_s3tc_srgb')
  15136. if (extension !== null) {
  15137. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT
  15138. if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
  15139. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
  15140. if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
  15141. } else {
  15142. return null
  15143. }
  15144. } else {
  15145. extension = extensions.get('WEBGL_compressed_texture_s3tc')
  15146. if (extension !== null) {
  15147. if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT
  15148. if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT
  15149. if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT
  15150. if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT
  15151. } else {
  15152. return null
  15153. }
  15154. }
  15155. }
  15156. // PVRTC
  15157. if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
  15158. extension = extensions.get('WEBGL_compressed_texture_pvrtc')
  15159. if (extension !== null) {
  15160. if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
  15161. if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
  15162. if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
  15163. if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
  15164. } else {
  15165. return null
  15166. }
  15167. }
  15168. // ETC1
  15169. if (p === RGB_ETC1_Format) {
  15170. extension = extensions.get('WEBGL_compressed_texture_etc1')
  15171. if (extension !== null) {
  15172. return extension.COMPRESSED_RGB_ETC1_WEBGL
  15173. } else {
  15174. return null
  15175. }
  15176. }
  15177. // ETC2
  15178. if (p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format) {
  15179. extension = extensions.get('WEBGL_compressed_texture_etc')
  15180. if (extension !== null) {
  15181. if (p === RGB_ETC2_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2
  15182. if (p === RGBA_ETC2_EAC_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC
  15183. } else {
  15184. return null
  15185. }
  15186. }
  15187. // ASTC
  15188. if (
  15189. p === RGBA_ASTC_4x4_Format ||
  15190. p === RGBA_ASTC_5x4_Format ||
  15191. p === RGBA_ASTC_5x5_Format ||
  15192. p === RGBA_ASTC_6x5_Format ||
  15193. p === RGBA_ASTC_6x6_Format ||
  15194. p === RGBA_ASTC_8x5_Format ||
  15195. p === RGBA_ASTC_8x6_Format ||
  15196. p === RGBA_ASTC_8x8_Format ||
  15197. p === RGBA_ASTC_10x5_Format ||
  15198. p === RGBA_ASTC_10x6_Format ||
  15199. p === RGBA_ASTC_10x8_Format ||
  15200. p === RGBA_ASTC_10x10_Format ||
  15201. p === RGBA_ASTC_12x10_Format ||
  15202. p === RGBA_ASTC_12x12_Format
  15203. ) {
  15204. extension = extensions.get('WEBGL_compressed_texture_astc')
  15205. if (extension !== null) {
  15206. if (p === RGBA_ASTC_4x4_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR
  15207. if (p === RGBA_ASTC_5x4_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR
  15208. if (p === RGBA_ASTC_5x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR
  15209. if (p === RGBA_ASTC_6x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR
  15210. if (p === RGBA_ASTC_6x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR
  15211. if (p === RGBA_ASTC_8x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR
  15212. if (p === RGBA_ASTC_8x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR
  15213. if (p === RGBA_ASTC_8x8_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR
  15214. if (p === RGBA_ASTC_10x5_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR
  15215. if (p === RGBA_ASTC_10x6_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR
  15216. if (p === RGBA_ASTC_10x8_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR
  15217. if (p === RGBA_ASTC_10x10_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR
  15218. if (p === RGBA_ASTC_12x10_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR
  15219. if (p === RGBA_ASTC_12x12_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR
  15220. } else {
  15221. return null
  15222. }
  15223. }
  15224. // BPTC
  15225. if (p === RGBA_BPTC_Format) {
  15226. extension = extensions.get('EXT_texture_compression_bptc')
  15227. if (extension !== null) {
  15228. if (p === RGBA_BPTC_Format) return encoding === sRGBEncoding ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT
  15229. } else {
  15230. return null
  15231. }
  15232. }
  15233. //
  15234. if (p === UnsignedInt248Type) {
  15235. if (isWebGL2) return 34042
  15236. extension = extensions.get('WEBGL_depth_texture')
  15237. if (extension !== null) {
  15238. return extension.UNSIGNED_INT_24_8_WEBGL
  15239. } else {
  15240. return null
  15241. }
  15242. }
  15243. // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
  15244. return gl[p] !== undefined ? gl[p] : null
  15245. }
  15246. return { convert: convert }
  15247. }
  15248. class ArrayCamera extends PerspectiveCamera {
  15249. constructor(array = []) {
  15250. super()
  15251. this.isArrayCamera = true
  15252. this.cameras = array
  15253. }
  15254. }
  15255. class Group extends Object3D {
  15256. constructor() {
  15257. super()
  15258. this.isGroup = true
  15259. this.type = 'Group'
  15260. }
  15261. }
  15262. const _moveEvent = { type: 'move' }
  15263. class WebXRController {
  15264. constructor() {
  15265. this._targetRay = null
  15266. this._grip = null
  15267. this._hand = null
  15268. }
  15269. getHandSpace() {
  15270. if (this._hand === null) {
  15271. this._hand = new Group()
  15272. this._hand.matrixAutoUpdate = false
  15273. this._hand.visible = false
  15274. this._hand.joints = {}
  15275. this._hand.inputState = { pinching: false }
  15276. }
  15277. return this._hand
  15278. }
  15279. getTargetRaySpace() {
  15280. if (this._targetRay === null) {
  15281. this._targetRay = new Group()
  15282. this._targetRay.matrixAutoUpdate = false
  15283. this._targetRay.visible = false
  15284. this._targetRay.hasLinearVelocity = false
  15285. this._targetRay.linearVelocity = new Vector3()
  15286. this._targetRay.hasAngularVelocity = false
  15287. this._targetRay.angularVelocity = new Vector3()
  15288. }
  15289. return this._targetRay
  15290. }
  15291. getGripSpace() {
  15292. if (this._grip === null) {
  15293. this._grip = new Group()
  15294. this._grip.matrixAutoUpdate = false
  15295. this._grip.visible = false
  15296. this._grip.hasLinearVelocity = false
  15297. this._grip.linearVelocity = new Vector3()
  15298. this._grip.hasAngularVelocity = false
  15299. this._grip.angularVelocity = new Vector3()
  15300. }
  15301. return this._grip
  15302. }
  15303. dispatchEvent(event) {
  15304. if (this._targetRay !== null) {
  15305. this._targetRay.dispatchEvent(event)
  15306. }
  15307. if (this._grip !== null) {
  15308. this._grip.dispatchEvent(event)
  15309. }
  15310. if (this._hand !== null) {
  15311. this._hand.dispatchEvent(event)
  15312. }
  15313. return this
  15314. }
  15315. disconnect(inputSource) {
  15316. this.dispatchEvent({ type: 'disconnected', data: inputSource })
  15317. if (this._targetRay !== null) {
  15318. this._targetRay.visible = false
  15319. }
  15320. if (this._grip !== null) {
  15321. this._grip.visible = false
  15322. }
  15323. if (this._hand !== null) {
  15324. this._hand.visible = false
  15325. }
  15326. return this
  15327. }
  15328. update(inputSource, frame, referenceSpace) {
  15329. let inputPose = null
  15330. let gripPose = null
  15331. let handPose = null
  15332. const targetRay = this._targetRay
  15333. const grip = this._grip
  15334. const hand = this._hand
  15335. if (inputSource && frame.session.visibilityState !== 'visible-blurred') {
  15336. if (targetRay !== null) {
  15337. inputPose = frame.getPose(inputSource.targetRaySpace, referenceSpace)
  15338. if (inputPose !== null) {
  15339. targetRay.matrix.fromArray(inputPose.transform.matrix)
  15340. targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale)
  15341. if (inputPose.linearVelocity) {
  15342. targetRay.hasLinearVelocity = true
  15343. targetRay.linearVelocity.copy(inputPose.linearVelocity)
  15344. } else {
  15345. targetRay.hasLinearVelocity = false
  15346. }
  15347. if (inputPose.angularVelocity) {
  15348. targetRay.hasAngularVelocity = true
  15349. targetRay.angularVelocity.copy(inputPose.angularVelocity)
  15350. } else {
  15351. targetRay.hasAngularVelocity = false
  15352. }
  15353. this.dispatchEvent(_moveEvent)
  15354. }
  15355. }
  15356. if (hand && inputSource.hand) {
  15357. handPose = true
  15358. for (const inputjoint of inputSource.hand.values()) {
  15359. // Update the joints groups with the XRJoint poses
  15360. const jointPose = frame.getJointPose(inputjoint, referenceSpace)
  15361. if (hand.joints[inputjoint.jointName] === undefined) {
  15362. // The transform of this joint will be updated with the joint pose on each frame
  15363. const joint = new Group()
  15364. joint.matrixAutoUpdate = false
  15365. joint.visible = false
  15366. hand.joints[inputjoint.jointName] = joint
  15367. // ??
  15368. hand.add(joint)
  15369. }
  15370. const joint = hand.joints[inputjoint.jointName]
  15371. if (jointPose !== null) {
  15372. joint.matrix.fromArray(jointPose.transform.matrix)
  15373. joint.matrix.decompose(joint.position, joint.rotation, joint.scale)
  15374. joint.jointRadius = jointPose.radius
  15375. }
  15376. joint.visible = jointPose !== null
  15377. }
  15378. // Custom events
  15379. // Check pinchz
  15380. const indexTip = hand.joints['index-finger-tip']
  15381. const thumbTip = hand.joints['thumb-tip']
  15382. const distance = indexTip.position.distanceTo(thumbTip.position)
  15383. const distanceToPinch = 0.02
  15384. const threshold = 0.005
  15385. if (hand.inputState.pinching && distance > distanceToPinch + threshold) {
  15386. hand.inputState.pinching = false
  15387. this.dispatchEvent({
  15388. type: 'pinchend',
  15389. handedness: inputSource.handedness,
  15390. target: this
  15391. })
  15392. } else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) {
  15393. hand.inputState.pinching = true
  15394. this.dispatchEvent({
  15395. type: 'pinchstart',
  15396. handedness: inputSource.handedness,
  15397. target: this
  15398. })
  15399. }
  15400. } else {
  15401. if (grip !== null && inputSource.gripSpace) {
  15402. gripPose = frame.getPose(inputSource.gripSpace, referenceSpace)
  15403. if (gripPose !== null) {
  15404. grip.matrix.fromArray(gripPose.transform.matrix)
  15405. grip.matrix.decompose(grip.position, grip.rotation, grip.scale)
  15406. if (gripPose.linearVelocity) {
  15407. grip.hasLinearVelocity = true
  15408. grip.linearVelocity.copy(gripPose.linearVelocity)
  15409. } else {
  15410. grip.hasLinearVelocity = false
  15411. }
  15412. if (gripPose.angularVelocity) {
  15413. grip.hasAngularVelocity = true
  15414. grip.angularVelocity.copy(gripPose.angularVelocity)
  15415. } else {
  15416. grip.hasAngularVelocity = false
  15417. }
  15418. }
  15419. }
  15420. }
  15421. }
  15422. if (targetRay !== null) {
  15423. targetRay.visible = inputPose !== null
  15424. }
  15425. if (grip !== null) {
  15426. grip.visible = gripPose !== null
  15427. }
  15428. if (hand !== null) {
  15429. hand.visible = handPose !== null
  15430. }
  15431. return this
  15432. }
  15433. }
  15434. class DepthTexture extends Texture {
  15435. constructor(width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format) {
  15436. format = format !== undefined ? format : DepthFormat
  15437. if (format !== DepthFormat && format !== DepthStencilFormat) {
  15438. throw new Error('DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat')
  15439. }
  15440. if (type === undefined && format === DepthFormat) type = UnsignedIntType
  15441. if (type === undefined && format === DepthStencilFormat) type = UnsignedInt248Type
  15442. super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy)
  15443. this.isDepthTexture = true
  15444. this.image = { width: width, height: height }
  15445. this.magFilter = magFilter !== undefined ? magFilter : NearestFilter
  15446. this.minFilter = minFilter !== undefined ? minFilter : NearestFilter
  15447. this.flipY = false
  15448. this.generateMipmaps = false
  15449. }
  15450. }
  15451. class WebXRManager extends EventDispatcher {
  15452. constructor(renderer, gl) {
  15453. super()
  15454. const scope = this
  15455. let session = null
  15456. let framebufferScaleFactor = 1.0
  15457. let referenceSpace = null
  15458. let referenceSpaceType = 'local-floor'
  15459. let customReferenceSpace = null
  15460. let pose = null
  15461. let glBinding = null
  15462. let glProjLayer = null
  15463. let glBaseLayer = null
  15464. let xrFrame = null
  15465. const attributes = gl.getContextAttributes()
  15466. let initialRenderTarget = null
  15467. let newRenderTarget = null
  15468. const controllers = []
  15469. const inputSourcesMap = new Map()
  15470. //
  15471. const cameraL = new PerspectiveCamera()
  15472. cameraL.layers.enable(1)
  15473. cameraL.viewport = new Vector4()
  15474. const cameraR = new PerspectiveCamera()
  15475. cameraR.layers.enable(2)
  15476. cameraR.viewport = new Vector4()
  15477. const cameras = [cameraL, cameraR]
  15478. const cameraVR = new ArrayCamera()
  15479. cameraVR.layers.enable(1)
  15480. cameraVR.layers.enable(2)
  15481. let _currentDepthNear = null
  15482. let _currentDepthFar = null
  15483. //
  15484. this.cameraAutoUpdate = true
  15485. this.enabled = false
  15486. this.isPresenting = false
  15487. this.getController = function(index) {
  15488. let controller = controllers[index]
  15489. if (controller === undefined) {
  15490. controller = new WebXRController()
  15491. controllers[index] = controller
  15492. }
  15493. return controller.getTargetRaySpace()
  15494. }
  15495. this.getControllerGrip = function(index) {
  15496. let controller = controllers[index]
  15497. if (controller === undefined) {
  15498. controller = new WebXRController()
  15499. controllers[index] = controller
  15500. }
  15501. return controller.getGripSpace()
  15502. }
  15503. this.getHand = function(index) {
  15504. let controller = controllers[index]
  15505. if (controller === undefined) {
  15506. controller = new WebXRController()
  15507. controllers[index] = controller
  15508. }
  15509. return controller.getHandSpace()
  15510. }
  15511. //
  15512. function onSessionEvent(event) {
  15513. const controller = inputSourcesMap.get(event.inputSource)
  15514. if (controller !== undefined) {
  15515. controller.dispatchEvent({ type: event.type, data: event.inputSource })
  15516. }
  15517. }
  15518. function onSessionEnd() {
  15519. session.removeEventListener('select', onSessionEvent)
  15520. session.removeEventListener('selectstart', onSessionEvent)
  15521. session.removeEventListener('selectend', onSessionEvent)
  15522. session.removeEventListener('squeeze', onSessionEvent)
  15523. session.removeEventListener('squeezestart', onSessionEvent)
  15524. session.removeEventListener('squeezeend', onSessionEvent)
  15525. session.removeEventListener('end', onSessionEnd)
  15526. session.removeEventListener('inputsourceschange', onInputSourcesChange)
  15527. inputSourcesMap.forEach(function(controller, inputSource) {
  15528. if (controller !== undefined) {
  15529. controller.disconnect(inputSource)
  15530. }
  15531. })
  15532. inputSourcesMap.clear()
  15533. _currentDepthNear = null
  15534. _currentDepthFar = null
  15535. // restore framebuffer/rendering state
  15536. renderer.setRenderTarget(initialRenderTarget)
  15537. glBaseLayer = null
  15538. glProjLayer = null
  15539. glBinding = null
  15540. session = null
  15541. newRenderTarget = null
  15542. //
  15543. animation.stop()
  15544. scope.isPresenting = false
  15545. scope.dispatchEvent({ type: 'sessionend' })
  15546. }
  15547. this.setFramebufferScaleFactor = function(value) {
  15548. framebufferScaleFactor = value
  15549. if (scope.isPresenting === true) {
  15550. console.warn('THREE.WebXRManager: Cannot change framebuffer scale while presenting.')
  15551. }
  15552. }
  15553. this.setReferenceSpaceType = function(value) {
  15554. referenceSpaceType = value
  15555. if (scope.isPresenting === true) {
  15556. console.warn('THREE.WebXRManager: Cannot change reference space type while presenting.')
  15557. }
  15558. }
  15559. this.getReferenceSpace = function() {
  15560. return customReferenceSpace || referenceSpace
  15561. }
  15562. this.setReferenceSpace = function(space) {
  15563. customReferenceSpace = space
  15564. }
  15565. this.getBaseLayer = function() {
  15566. return glProjLayer !== null ? glProjLayer : glBaseLayer
  15567. }
  15568. this.getBinding = function() {
  15569. return glBinding
  15570. }
  15571. this.getFrame = function() {
  15572. return xrFrame
  15573. }
  15574. this.getSession = function() {
  15575. return session
  15576. }
  15577. this.setSession = async function(value) {
  15578. session = value
  15579. if (session !== null) {
  15580. initialRenderTarget = renderer.getRenderTarget()
  15581. session.addEventListener('select', onSessionEvent)
  15582. session.addEventListener('selectstart', onSessionEvent)
  15583. session.addEventListener('selectend', onSessionEvent)
  15584. session.addEventListener('squeeze', onSessionEvent)
  15585. session.addEventListener('squeezestart', onSessionEvent)
  15586. session.addEventListener('squeezeend', onSessionEvent)
  15587. session.addEventListener('end', onSessionEnd)
  15588. session.addEventListener('inputsourceschange', onInputSourcesChange)
  15589. if (attributes.xrCompatible !== true) {
  15590. await gl.makeXRCompatible()
  15591. }
  15592. if (session.renderState.layers === undefined || renderer.capabilities.isWebGL2 === false) {
  15593. const layerInit = {
  15594. antialias: session.renderState.layers === undefined ? attributes.antialias : true,
  15595. alpha: attributes.alpha,
  15596. depth: attributes.depth,
  15597. stencil: attributes.stencil,
  15598. framebufferScaleFactor: framebufferScaleFactor
  15599. }
  15600. glBaseLayer = new XRWebGLLayer(session, gl, layerInit)
  15601. session.updateRenderState({ baseLayer: glBaseLayer })
  15602. newRenderTarget = new WebGLRenderTarget(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, {
  15603. format: RGBAFormat,
  15604. type: UnsignedByteType,
  15605. encoding: renderer.outputEncoding
  15606. })
  15607. } else {
  15608. let depthFormat = null
  15609. let depthType = null
  15610. let glDepthFormat = null
  15611. if (attributes.depth) {
  15612. glDepthFormat = attributes.stencil ? 35056 : 33190
  15613. depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat
  15614. depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType
  15615. }
  15616. const projectionlayerInit = {
  15617. colorFormat: renderer.outputEncoding === sRGBEncoding ? 35907 : 32856,
  15618. depthFormat: glDepthFormat,
  15619. scaleFactor: framebufferScaleFactor
  15620. }
  15621. glBinding = new XRWebGLBinding(session, gl)
  15622. glProjLayer = glBinding.createProjectionLayer(projectionlayerInit)
  15623. session.updateRenderState({ layers: [glProjLayer] })
  15624. newRenderTarget = new WebGLRenderTarget(glProjLayer.textureWidth, glProjLayer.textureHeight, {
  15625. format: RGBAFormat,
  15626. type: UnsignedByteType,
  15627. depthTexture: new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat),
  15628. stencilBuffer: attributes.stencil,
  15629. encoding: renderer.outputEncoding,
  15630. samples: attributes.antialias ? 4 : 0
  15631. })
  15632. const renderTargetProperties = renderer.properties.get(newRenderTarget)
  15633. renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues
  15634. }
  15635. newRenderTarget.isXRRenderTarget = true // TODO Remove this when possible, see #23278
  15636. // Set foveation to maximum.
  15637. this.setFoveation(1.0)
  15638. customReferenceSpace = null
  15639. referenceSpace = await session.requestReferenceSpace(referenceSpaceType)
  15640. animation.setContext(session)
  15641. animation.start()
  15642. scope.isPresenting = true
  15643. scope.dispatchEvent({ type: 'sessionstart' })
  15644. }
  15645. }
  15646. function onInputSourcesChange(event) {
  15647. const inputSources = session.inputSources
  15648. // Assign controllers to available inputSources
  15649. for (let i = 0; i < inputSources.length; i++) {
  15650. const index = inputSources[i].handedness === 'right' ? 1 : 0
  15651. inputSourcesMap.set(inputSources[i], controllers[index])
  15652. }
  15653. // Notify disconnected
  15654. for (let i = 0; i < event.removed.length; i++) {
  15655. const inputSource = event.removed[i]
  15656. const controller = inputSourcesMap.get(inputSource)
  15657. if (controller) {
  15658. controller.dispatchEvent({ type: 'disconnected', data: inputSource })
  15659. inputSourcesMap.delete(inputSource)
  15660. }
  15661. }
  15662. // Notify connected
  15663. for (let i = 0; i < event.added.length; i++) {
  15664. const inputSource = event.added[i]
  15665. const controller = inputSourcesMap.get(inputSource)
  15666. if (controller) {
  15667. controller.dispatchEvent({ type: 'connected', data: inputSource })
  15668. }
  15669. }
  15670. }
  15671. //
  15672. const cameraLPos = new Vector3()
  15673. const cameraRPos = new Vector3()
  15674. /**
  15675. * Assumes 2 cameras that are parallel and share an X-axis, and that
  15676. * the cameras' projection and world matrices have already been set.
  15677. * And that near and far planes are identical for both cameras.
  15678. * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
  15679. */
  15680. function setProjectionFromUnion(camera, cameraL, cameraR) {
  15681. cameraLPos.setFromMatrixPosition(cameraL.matrixWorld)
  15682. cameraRPos.setFromMatrixPosition(cameraR.matrixWorld)
  15683. const ipd = cameraLPos.distanceTo(cameraRPos)
  15684. const projL = cameraL.projectionMatrix.elements
  15685. const projR = cameraR.projectionMatrix.elements
  15686. // VR systems will have identical far and near planes, and
  15687. // most likely identical top and bottom frustum extents.
  15688. // Use the left camera for these values.
  15689. const near = projL[14] / (projL[10] - 1)
  15690. const far = projL[14] / (projL[10] + 1)
  15691. const topFov = (projL[9] + 1) / projL[5]
  15692. const bottomFov = (projL[9] - 1) / projL[5]
  15693. const leftFov = (projL[8] - 1) / projL[0]
  15694. const rightFov = (projR[8] + 1) / projR[0]
  15695. const left = near * leftFov
  15696. const right = near * rightFov
  15697. // Calculate the new camera's position offset from the
  15698. // left camera. xOffset should be roughly half `ipd`.
  15699. const zOffset = ipd / (-leftFov + rightFov)
  15700. const xOffset = zOffset * -leftFov
  15701. // TODO: Better way to apply this offset?
  15702. cameraL.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale)
  15703. camera.translateX(xOffset)
  15704. camera.translateZ(zOffset)
  15705. camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale)
  15706. camera.matrixWorldInverse.copy(camera.matrixWorld).invert()
  15707. // Find the union of the frustum values of the cameras and scale
  15708. // the values so that the near plane's position does not change in world space,
  15709. // although must now be relative to the new union camera.
  15710. const near2 = near + zOffset
  15711. const far2 = far + zOffset
  15712. const left2 = left - xOffset
  15713. const right2 = right + (ipd - xOffset)
  15714. const top2 = ((topFov * far) / far2) * near2
  15715. const bottom2 = ((bottomFov * far) / far2) * near2
  15716. camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2)
  15717. }
  15718. function updateCamera(camera, parent) {
  15719. if (parent === null) {
  15720. camera.matrixWorld.copy(camera.matrix)
  15721. } else {
  15722. camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix)
  15723. }
  15724. camera.matrixWorldInverse.copy(camera.matrixWorld).invert()
  15725. }
  15726. this.updateCamera = function(camera) {
  15727. if (session === null) return
  15728. cameraVR.near = cameraR.near = cameraL.near = camera.near
  15729. cameraVR.far = cameraR.far = cameraL.far = camera.far
  15730. if (_currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far) {
  15731. // Note that the new renderState won't apply until the next frame. See #18320
  15732. session.updateRenderState({
  15733. depthNear: cameraVR.near,
  15734. depthFar: cameraVR.far
  15735. })
  15736. _currentDepthNear = cameraVR.near
  15737. _currentDepthFar = cameraVR.far
  15738. }
  15739. const parent = camera.parent
  15740. const cameras = cameraVR.cameras
  15741. updateCamera(cameraVR, parent)
  15742. for (let i = 0; i < cameras.length; i++) {
  15743. updateCamera(cameras[i], parent)
  15744. }
  15745. cameraVR.matrixWorld.decompose(cameraVR.position, cameraVR.quaternion, cameraVR.scale)
  15746. // update user camera and its children
  15747. camera.position.copy(cameraVR.position)
  15748. camera.quaternion.copy(cameraVR.quaternion)
  15749. camera.scale.copy(cameraVR.scale)
  15750. camera.matrix.copy(cameraVR.matrix)
  15751. camera.matrixWorld.copy(cameraVR.matrixWorld)
  15752. const children = camera.children
  15753. for (let i = 0, l = children.length; i < l; i++) {
  15754. children[i].updateMatrixWorld(true)
  15755. }
  15756. // update projection matrix for proper view frustum culling
  15757. if (cameras.length === 2) {
  15758. setProjectionFromUnion(cameraVR, cameraL, cameraR)
  15759. } else {
  15760. // assume single camera setup (AR)
  15761. cameraVR.projectionMatrix.copy(cameraL.projectionMatrix)
  15762. }
  15763. }
  15764. this.getCamera = function() {
  15765. return cameraVR
  15766. }
  15767. this.getFoveation = function() {
  15768. if (glProjLayer !== null) {
  15769. return glProjLayer.fixedFoveation
  15770. }
  15771. if (glBaseLayer !== null) {
  15772. return glBaseLayer.fixedFoveation
  15773. }
  15774. return undefined
  15775. }
  15776. this.setFoveation = function(foveation) {
  15777. // 0 = no foveation = full resolution
  15778. // 1 = maximum foveation = the edges render at lower resolution
  15779. if (glProjLayer !== null) {
  15780. glProjLayer.fixedFoveation = foveation
  15781. }
  15782. if (glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined) {
  15783. glBaseLayer.fixedFoveation = foveation
  15784. }
  15785. }
  15786. // Animation Loop
  15787. let onAnimationFrameCallback = null
  15788. function onAnimationFrame(time, frame) {
  15789. pose = frame.getViewerPose(customReferenceSpace || referenceSpace)
  15790. xrFrame = frame
  15791. if (pose !== null) {
  15792. const views = pose.views
  15793. if (glBaseLayer !== null) {
  15794. renderer.setRenderTargetFramebuffer(newRenderTarget, glBaseLayer.framebuffer)
  15795. renderer.setRenderTarget(newRenderTarget)
  15796. }
  15797. let cameraVRNeedsUpdate = false
  15798. // check if it's necessary to rebuild cameraVR's camera list
  15799. if (views.length !== cameraVR.cameras.length) {
  15800. cameraVR.cameras.length = 0
  15801. cameraVRNeedsUpdate = true
  15802. }
  15803. for (let i = 0; i < views.length; i++) {
  15804. const view = views[i]
  15805. let viewport = null
  15806. if (glBaseLayer !== null) {
  15807. viewport = glBaseLayer.getViewport(view)
  15808. } else {
  15809. const glSubImage = glBinding.getViewSubImage(glProjLayer, view)
  15810. viewport = glSubImage.viewport
  15811. // For side-by-side projection, we only produce a single texture for both eyes.
  15812. if (i === 0) {
  15813. renderer.setRenderTargetTextures(newRenderTarget, glSubImage.colorTexture, glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture)
  15814. renderer.setRenderTarget(newRenderTarget)
  15815. }
  15816. }
  15817. let camera = cameras[i]
  15818. if (camera === undefined) {
  15819. camera = new PerspectiveCamera()
  15820. camera.layers.enable(i)
  15821. camera.viewport = new Vector4()
  15822. cameras[i] = camera
  15823. }
  15824. camera.matrix.fromArray(view.transform.matrix)
  15825. camera.projectionMatrix.fromArray(view.projectionMatrix)
  15826. camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height)
  15827. if (i === 0) {
  15828. cameraVR.matrix.copy(camera.matrix)
  15829. }
  15830. if (cameraVRNeedsUpdate === true) {
  15831. cameraVR.cameras.push(camera)
  15832. }
  15833. }
  15834. }
  15835. //
  15836. const inputSources = session.inputSources
  15837. for (let i = 0; i < controllers.length; i++) {
  15838. const inputSource = inputSources[i]
  15839. const controller = inputSourcesMap.get(inputSource)
  15840. if (controller !== undefined) {
  15841. controller.update(inputSource, frame, customReferenceSpace || referenceSpace)
  15842. }
  15843. }
  15844. if (onAnimationFrameCallback) onAnimationFrameCallback(time, frame)
  15845. xrFrame = null
  15846. }
  15847. const animation = new WebGLAnimation()
  15848. animation.setAnimationLoop(onAnimationFrame)
  15849. this.setAnimationLoop = function(callback) {
  15850. onAnimationFrameCallback = callback
  15851. }
  15852. this.dispose = function() {}
  15853. }
  15854. }
  15855. function WebGLMaterials(renderer, properties) {
  15856. function refreshFogUniforms(uniforms, fog) {
  15857. uniforms.fogColor.value.copy(fog.color)
  15858. if (fog.isFog) {
  15859. uniforms.fogNear.value = fog.near
  15860. uniforms.fogFar.value = fog.far
  15861. } else if (fog.isFogExp2) {
  15862. uniforms.fogDensity.value = fog.density
  15863. }
  15864. }
  15865. function refreshMaterialUniforms(uniforms, material, pixelRatio, height, transmissionRenderTarget) {
  15866. if (material.isMeshBasicMaterial) {
  15867. refreshUniformsCommon(uniforms, material)
  15868. } else if (material.isMeshLambertMaterial) {
  15869. refreshUniformsCommon(uniforms, material)
  15870. } else if (material.isMeshToonMaterial) {
  15871. refreshUniformsCommon(uniforms, material)
  15872. refreshUniformsToon(uniforms, material)
  15873. } else if (material.isMeshPhongMaterial) {
  15874. refreshUniformsCommon(uniforms, material)
  15875. refreshUniformsPhong(uniforms, material)
  15876. } else if (material.isMeshStandardMaterial) {
  15877. refreshUniformsCommon(uniforms, material)
  15878. refreshUniformsStandard(uniforms, material)
  15879. if (material.isMeshPhysicalMaterial) {
  15880. refreshUniformsPhysical(uniforms, material, transmissionRenderTarget)
  15881. }
  15882. } else if (material.isMeshMatcapMaterial) {
  15883. refreshUniformsCommon(uniforms, material)
  15884. refreshUniformsMatcap(uniforms, material)
  15885. } else if (material.isMeshDepthMaterial) {
  15886. refreshUniformsCommon(uniforms, material)
  15887. } else if (material.isMeshDistanceMaterial) {
  15888. refreshUniformsCommon(uniforms, material)
  15889. refreshUniformsDistance(uniforms, material)
  15890. } else if (material.isMeshNormalMaterial) {
  15891. refreshUniformsCommon(uniforms, material)
  15892. } else if (material.isLineBasicMaterial) {
  15893. refreshUniformsLine(uniforms, material)
  15894. if (material.isLineDashedMaterial) {
  15895. refreshUniformsDash(uniforms, material)
  15896. }
  15897. } else if (material.isPointsMaterial) {
  15898. refreshUniformsPoints(uniforms, material, pixelRatio, height)
  15899. } else if (material.isSpriteMaterial) {
  15900. refreshUniformsSprites(uniforms, material)
  15901. } else if (material.isShadowMaterial) {
  15902. uniforms.color.value.copy(material.color)
  15903. uniforms.opacity.value = material.opacity
  15904. } else if (material.isShaderMaterial) {
  15905. material.uniformsNeedUpdate = false // #15581
  15906. }
  15907. }
  15908. function refreshUniformsCommon(uniforms, material) {
  15909. uniforms.opacity.value = material.opacity
  15910. if (material.color) {
  15911. uniforms.diffuse.value.copy(material.color)
  15912. }
  15913. if (material.emissive) {
  15914. uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity)
  15915. }
  15916. if (material.map) {
  15917. uniforms.map.value = material.map
  15918. }
  15919. if (material.alphaMap) {
  15920. uniforms.alphaMap.value = material.alphaMap
  15921. }
  15922. if (material.bumpMap) {
  15923. uniforms.bumpMap.value = material.bumpMap
  15924. uniforms.bumpScale.value = material.bumpScale
  15925. if (material.side === BackSide) uniforms.bumpScale.value *= -1
  15926. }
  15927. if (material.displacementMap) {
  15928. uniforms.displacementMap.value = material.displacementMap
  15929. uniforms.displacementScale.value = material.displacementScale
  15930. uniforms.displacementBias.value = material.displacementBias
  15931. }
  15932. if (material.emissiveMap) {
  15933. uniforms.emissiveMap.value = material.emissiveMap
  15934. }
  15935. if (material.normalMap) {
  15936. uniforms.normalMap.value = material.normalMap
  15937. uniforms.normalScale.value.copy(material.normalScale)
  15938. if (material.side === BackSide) uniforms.normalScale.value.negate()
  15939. }
  15940. if (material.specularMap) {
  15941. uniforms.specularMap.value = material.specularMap
  15942. }
  15943. if (material.alphaTest > 0) {
  15944. uniforms.alphaTest.value = material.alphaTest
  15945. }
  15946. const envMap = properties.get(material).envMap
  15947. if (envMap) {
  15948. uniforms.envMap.value = envMap
  15949. uniforms.flipEnvMap.value = envMap.isCubeTexture && envMap.isRenderTargetTexture === false ? -1 : 1
  15950. uniforms.reflectivity.value = material.reflectivity
  15951. uniforms.ior.value = material.ior
  15952. uniforms.refractionRatio.value = material.refractionRatio
  15953. }
  15954. if (material.lightMap) {
  15955. uniforms.lightMap.value = material.lightMap
  15956. // artist-friendly light intensity scaling factor
  15957. const scaleFactor = renderer.physicallyCorrectLights !== true ? Math.PI : 1
  15958. uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor
  15959. }
  15960. if (material.aoMap) {
  15961. uniforms.aoMap.value = material.aoMap
  15962. uniforms.aoMapIntensity.value = material.aoMapIntensity
  15963. }
  15964. // uv repeat and offset setting priorities
  15965. // 1. color map
  15966. // 2. specular map
  15967. // 3. displacementMap map
  15968. // 4. normal map
  15969. // 5. bump map
  15970. // 6. roughnessMap map
  15971. // 7. metalnessMap map
  15972. // 8. alphaMap map
  15973. // 9. emissiveMap map
  15974. // 10. clearcoat map
  15975. // 11. clearcoat normal map
  15976. // 12. clearcoat roughnessMap map
  15977. // 13. iridescence map
  15978. // 14. iridescence thickness map
  15979. // 15. specular intensity map
  15980. // 16. specular tint map
  15981. // 17. transmission map
  15982. // 18. thickness map
  15983. let uvScaleMap
  15984. if (material.map) {
  15985. uvScaleMap = material.map
  15986. } else if (material.specularMap) {
  15987. uvScaleMap = material.specularMap
  15988. } else if (material.displacementMap) {
  15989. uvScaleMap = material.displacementMap
  15990. } else if (material.normalMap) {
  15991. uvScaleMap = material.normalMap
  15992. } else if (material.bumpMap) {
  15993. uvScaleMap = material.bumpMap
  15994. } else if (material.roughnessMap) {
  15995. uvScaleMap = material.roughnessMap
  15996. } else if (material.metalnessMap) {
  15997. uvScaleMap = material.metalnessMap
  15998. } else if (material.alphaMap) {
  15999. uvScaleMap = material.alphaMap
  16000. } else if (material.emissiveMap) {
  16001. uvScaleMap = material.emissiveMap
  16002. } else if (material.clearcoatMap) {
  16003. uvScaleMap = material.clearcoatMap
  16004. } else if (material.clearcoatNormalMap) {
  16005. uvScaleMap = material.clearcoatNormalMap
  16006. } else if (material.clearcoatRoughnessMap) {
  16007. uvScaleMap = material.clearcoatRoughnessMap
  16008. } else if (material.iridescenceMap) {
  16009. uvScaleMap = material.iridescenceMap
  16010. } else if (material.iridescenceThicknessMap) {
  16011. uvScaleMap = material.iridescenceThicknessMap
  16012. } else if (material.specularIntensityMap) {
  16013. uvScaleMap = material.specularIntensityMap
  16014. } else if (material.specularColorMap) {
  16015. uvScaleMap = material.specularColorMap
  16016. } else if (material.transmissionMap) {
  16017. uvScaleMap = material.transmissionMap
  16018. } else if (material.thicknessMap) {
  16019. uvScaleMap = material.thicknessMap
  16020. } else if (material.sheenColorMap) {
  16021. uvScaleMap = material.sheenColorMap
  16022. } else if (material.sheenRoughnessMap) {
  16023. uvScaleMap = material.sheenRoughnessMap
  16024. }
  16025. if (uvScaleMap !== undefined) {
  16026. // backwards compatibility
  16027. if (uvScaleMap.isWebGLRenderTarget) {
  16028. uvScaleMap = uvScaleMap.texture
  16029. }
  16030. if (uvScaleMap.matrixAutoUpdate === true) {
  16031. uvScaleMap.updateMatrix()
  16032. }
  16033. uniforms.uvTransform.value.copy(uvScaleMap.matrix)
  16034. }
  16035. // uv repeat and offset setting priorities for uv2
  16036. // 1. ao map
  16037. // 2. light map
  16038. let uv2ScaleMap
  16039. if (material.aoMap) {
  16040. uv2ScaleMap = material.aoMap
  16041. } else if (material.lightMap) {
  16042. uv2ScaleMap = material.lightMap
  16043. }
  16044. if (uv2ScaleMap !== undefined) {
  16045. // backwards compatibility
  16046. if (uv2ScaleMap.isWebGLRenderTarget) {
  16047. uv2ScaleMap = uv2ScaleMap.texture
  16048. }
  16049. if (uv2ScaleMap.matrixAutoUpdate === true) {
  16050. uv2ScaleMap.updateMatrix()
  16051. }
  16052. uniforms.uv2Transform.value.copy(uv2ScaleMap.matrix)
  16053. }
  16054. }
  16055. function refreshUniformsLine(uniforms, material) {
  16056. uniforms.diffuse.value.copy(material.color)
  16057. uniforms.opacity.value = material.opacity
  16058. }
  16059. function refreshUniformsDash(uniforms, material) {
  16060. uniforms.dashSize.value = material.dashSize
  16061. uniforms.totalSize.value = material.dashSize + material.gapSize
  16062. uniforms.scale.value = material.scale
  16063. }
  16064. function refreshUniformsPoints(uniforms, material, pixelRatio, height) {
  16065. uniforms.diffuse.value.copy(material.color)
  16066. uniforms.opacity.value = material.opacity
  16067. uniforms.size.value = material.size * pixelRatio
  16068. uniforms.scale.value = height * 0.5
  16069. if (material.map) {
  16070. uniforms.map.value = material.map
  16071. }
  16072. if (material.alphaMap) {
  16073. uniforms.alphaMap.value = material.alphaMap
  16074. }
  16075. if (material.alphaTest > 0) {
  16076. uniforms.alphaTest.value = material.alphaTest
  16077. }
  16078. // uv repeat and offset setting priorities
  16079. // 1. color map
  16080. // 2. alpha map
  16081. let uvScaleMap
  16082. if (material.map) {
  16083. uvScaleMap = material.map
  16084. } else if (material.alphaMap) {
  16085. uvScaleMap = material.alphaMap
  16086. }
  16087. if (uvScaleMap !== undefined) {
  16088. if (uvScaleMap.matrixAutoUpdate === true) {
  16089. uvScaleMap.updateMatrix()
  16090. }
  16091. uniforms.uvTransform.value.copy(uvScaleMap.matrix)
  16092. }
  16093. }
  16094. function refreshUniformsSprites(uniforms, material) {
  16095. uniforms.diffuse.value.copy(material.color)
  16096. uniforms.opacity.value = material.opacity
  16097. uniforms.rotation.value = material.rotation
  16098. if (material.map) {
  16099. uniforms.map.value = material.map
  16100. }
  16101. if (material.alphaMap) {
  16102. uniforms.alphaMap.value = material.alphaMap
  16103. }
  16104. if (material.alphaTest > 0) {
  16105. uniforms.alphaTest.value = material.alphaTest
  16106. }
  16107. // uv repeat and offset setting priorities
  16108. // 1. color map
  16109. // 2. alpha map
  16110. let uvScaleMap
  16111. if (material.map) {
  16112. uvScaleMap = material.map
  16113. } else if (material.alphaMap) {
  16114. uvScaleMap = material.alphaMap
  16115. }
  16116. if (uvScaleMap !== undefined) {
  16117. if (uvScaleMap.matrixAutoUpdate === true) {
  16118. uvScaleMap.updateMatrix()
  16119. }
  16120. uniforms.uvTransform.value.copy(uvScaleMap.matrix)
  16121. }
  16122. }
  16123. function refreshUniformsPhong(uniforms, material) {
  16124. uniforms.specular.value.copy(material.specular)
  16125. uniforms.shininess.value = Math.max(material.shininess, 1e-4) // to prevent pow( 0.0, 0.0 )
  16126. }
  16127. function refreshUniformsToon(uniforms, material) {
  16128. if (material.gradientMap) {
  16129. uniforms.gradientMap.value = material.gradientMap
  16130. }
  16131. }
  16132. function refreshUniformsStandard(uniforms, material) {
  16133. uniforms.roughness.value = material.roughness
  16134. uniforms.metalness.value = material.metalness
  16135. if (material.roughnessMap) {
  16136. uniforms.roughnessMap.value = material.roughnessMap
  16137. }
  16138. if (material.metalnessMap) {
  16139. uniforms.metalnessMap.value = material.metalnessMap
  16140. }
  16141. const envMap = properties.get(material).envMap
  16142. if (envMap) {
  16143. //uniforms.envMap.value = material.envMap; // part of uniforms common
  16144. uniforms.envMapIntensity.value = material.envMapIntensity
  16145. }
  16146. }
  16147. function refreshUniformsPhysical(uniforms, material, transmissionRenderTarget) {
  16148. uniforms.ior.value = material.ior // also part of uniforms common
  16149. if (material.sheen > 0) {
  16150. uniforms.sheenColor.value.copy(material.sheenColor).multiplyScalar(material.sheen)
  16151. uniforms.sheenRoughness.value = material.sheenRoughness
  16152. if (material.sheenColorMap) {
  16153. uniforms.sheenColorMap.value = material.sheenColorMap
  16154. }
  16155. if (material.sheenRoughnessMap) {
  16156. uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap
  16157. }
  16158. }
  16159. if (material.clearcoat > 0) {
  16160. uniforms.clearcoat.value = material.clearcoat
  16161. uniforms.clearcoatRoughness.value = material.clearcoatRoughness
  16162. if (material.clearcoatMap) {
  16163. uniforms.clearcoatMap.value = material.clearcoatMap
  16164. }
  16165. if (material.clearcoatRoughnessMap) {
  16166. uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap
  16167. }
  16168. if (material.clearcoatNormalMap) {
  16169. uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale)
  16170. uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap
  16171. if (material.side === BackSide) {
  16172. uniforms.clearcoatNormalScale.value.negate()
  16173. }
  16174. }
  16175. }
  16176. if (material.iridescence > 0) {
  16177. uniforms.iridescence.value = material.iridescence
  16178. uniforms.iridescenceIOR.value = material.iridescenceIOR
  16179. uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[0]
  16180. uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[1]
  16181. if (material.iridescenceMap) {
  16182. uniforms.iridescenceMap.value = material.iridescenceMap
  16183. }
  16184. if (material.iridescenceThicknessMap) {
  16185. uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap
  16186. }
  16187. }
  16188. if (material.transmission > 0) {
  16189. uniforms.transmission.value = material.transmission
  16190. uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture
  16191. uniforms.transmissionSamplerSize.value.set(transmissionRenderTarget.width, transmissionRenderTarget.height)
  16192. if (material.transmissionMap) {
  16193. uniforms.transmissionMap.value = material.transmissionMap
  16194. }
  16195. uniforms.thickness.value = material.thickness
  16196. if (material.thicknessMap) {
  16197. uniforms.thicknessMap.value = material.thicknessMap
  16198. }
  16199. uniforms.attenuationDistance.value = material.attenuationDistance
  16200. uniforms.attenuationColor.value.copy(material.attenuationColor)
  16201. }
  16202. uniforms.specularIntensity.value = material.specularIntensity
  16203. uniforms.specularColor.value.copy(material.specularColor)
  16204. if (material.specularIntensityMap) {
  16205. uniforms.specularIntensityMap.value = material.specularIntensityMap
  16206. }
  16207. if (material.specularColorMap) {
  16208. uniforms.specularColorMap.value = material.specularColorMap
  16209. }
  16210. }
  16211. function refreshUniformsMatcap(uniforms, material) {
  16212. if (material.matcap) {
  16213. uniforms.matcap.value = material.matcap
  16214. }
  16215. }
  16216. function refreshUniformsDistance(uniforms, material) {
  16217. uniforms.referencePosition.value.copy(material.referencePosition)
  16218. uniforms.nearDistance.value = material.nearDistance
  16219. uniforms.farDistance.value = material.farDistance
  16220. }
  16221. return {
  16222. refreshFogUniforms: refreshFogUniforms,
  16223. refreshMaterialUniforms: refreshMaterialUniforms
  16224. }
  16225. }
  16226. function createCanvasElement() {
  16227. const canvas = createElementNS('canvas')
  16228. canvas.style.display = 'block'
  16229. return canvas
  16230. }
  16231. function WebGLRenderer(parameters = {}) {
  16232. this.isWebGLRenderer = true
  16233. const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
  16234. _context = parameters.context !== undefined ? parameters.context : null,
  16235. _depth = parameters.depth !== undefined ? parameters.depth : true,
  16236. _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
  16237. _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
  16238. _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
  16239. _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
  16240. _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
  16241. _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false
  16242. let _alpha
  16243. if (_context !== null) {
  16244. _alpha = _context.getContextAttributes().alpha
  16245. } else {
  16246. _alpha = parameters.alpha !== undefined ? parameters.alpha : false
  16247. }
  16248. let currentRenderList = null
  16249. let currentRenderState = null
  16250. // render() can be called from within a callback triggered by another render.
  16251. // We track this so that the nested render call gets its list and state isolated from the parent render call.
  16252. const renderListStack = []
  16253. const renderStateStack = []
  16254. // public properties
  16255. this.domElement = _canvas
  16256. // Debug configuration container
  16257. this.debug = {
  16258. /**
  16259. * Enables error checking and reporting when shader programs are being compiled
  16260. * @type {boolean}
  16261. */
  16262. checkShaderErrors: true
  16263. }
  16264. // clearing
  16265. this.autoClear = true
  16266. this.autoClearColor = true
  16267. this.autoClearDepth = true
  16268. this.autoClearStencil = true
  16269. // scene graph
  16270. this.sortObjects = true
  16271. // user-defined clipping
  16272. this.clippingPlanes = []
  16273. this.localClippingEnabled = false
  16274. // physically based shading
  16275. this.outputEncoding = LinearEncoding
  16276. // physical lights
  16277. this.physicallyCorrectLights = false
  16278. // tone mapping
  16279. this.toneMapping = NoToneMapping
  16280. this.toneMappingExposure = 1.0
  16281. //
  16282. Object.defineProperties(this, {
  16283. // @deprecated since r136, 0e21088102b4de7e0a0a33140620b7a3424b9e6d
  16284. gammaFactor: {
  16285. get: function() {
  16286. console.warn('THREE.WebGLRenderer: .gammaFactor has been removed.')
  16287. return 2
  16288. },
  16289. set: function() {
  16290. console.warn('THREE.WebGLRenderer: .gammaFactor has been removed.')
  16291. }
  16292. }
  16293. })
  16294. // internal properties
  16295. const _this = this
  16296. let _isContextLost = false
  16297. // internal state cache
  16298. let _currentActiveCubeFace = 0
  16299. let _currentActiveMipmapLevel = 0
  16300. let _currentRenderTarget = null
  16301. let _currentMaterialId = -1
  16302. let _currentCamera = null
  16303. const _currentViewport = new Vector4()
  16304. const _currentScissor = new Vector4()
  16305. let _currentScissorTest = null
  16306. //
  16307. let _width = _canvas.width
  16308. let _height = _canvas.height
  16309. let _pixelRatio = 1
  16310. let _opaqueSort = null
  16311. let _transparentSort = null
  16312. const _viewport = new Vector4(0, 0, _width, _height)
  16313. const _scissor = new Vector4(0, 0, _width, _height)
  16314. let _scissorTest = false
  16315. // frustum
  16316. const _frustum = new Frustum()
  16317. // clipping
  16318. let _clippingEnabled = false
  16319. let _localClippingEnabled = false
  16320. // transmission
  16321. let _transmissionRenderTarget = null
  16322. // camera matrices cache
  16323. const _projScreenMatrix = new Matrix4()
  16324. const _vector2 = new Vector2()
  16325. const _vector3 = new Vector3()
  16326. const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }
  16327. function getTargetPixelRatio() {
  16328. return _currentRenderTarget === null ? _pixelRatio : 1
  16329. }
  16330. // initialize
  16331. let _gl = _context
  16332. function getContext(contextNames, contextAttributes) {
  16333. for (let i = 0; i < contextNames.length; i++) {
  16334. const contextName = contextNames[i]
  16335. const context = _canvas.getContext(contextName, contextAttributes)
  16336. if (context !== null) return context
  16337. }
  16338. return null
  16339. }
  16340. try {
  16341. const contextAttributes = {
  16342. alpha: true,
  16343. depth: _depth,
  16344. stencil: _stencil,
  16345. antialias: _antialias,
  16346. premultipliedAlpha: _premultipliedAlpha,
  16347. preserveDrawingBuffer: _preserveDrawingBuffer,
  16348. powerPreference: _powerPreference,
  16349. failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
  16350. }
  16351. // OffscreenCanvas does not have setAttribute, see #22811
  16352. if ('setAttribute' in _canvas) _canvas.setAttribute('data-engine', `three.js r${REVISION}`)
  16353. // event listeners must be registered before WebGL context is created, see #12753
  16354. _canvas.addEventListener('webglcontextlost', onContextLost, false)
  16355. _canvas.addEventListener('webglcontextrestored', onContextRestore, false)
  16356. _canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false)
  16357. if (_gl === null) {
  16358. const contextNames = ['webgl2', 'webgl', 'experimental-webgl']
  16359. if (_this.isWebGL1Renderer === true) {
  16360. contextNames.shift()
  16361. }
  16362. _gl = getContext(contextNames, contextAttributes)
  16363. if (_gl === null) {
  16364. if (getContext(contextNames)) {
  16365. throw new Error('Error creating WebGL context with your selected attributes.')
  16366. } else {
  16367. throw new Error('Error creating WebGL context.')
  16368. }
  16369. }
  16370. }
  16371. // Some experimental-webgl implementations do not have getShaderPrecisionFormat
  16372. if (_gl.getShaderPrecisionFormat === undefined) {
  16373. _gl.getShaderPrecisionFormat = function() {
  16374. return { rangeMin: 1, rangeMax: 1, precision: 1 }
  16375. }
  16376. }
  16377. } catch (error) {
  16378. console.error('THREE.WebGLRenderer: ' + error.message)
  16379. throw error
  16380. }
  16381. let extensions, capabilities, state, info
  16382. let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects
  16383. let programCache, materials, renderLists, renderStates, clipping, shadowMap
  16384. let background, morphtargets, bufferRenderer, indexedBufferRenderer
  16385. let utils, bindingStates
  16386. function initGLContext() {
  16387. extensions = new WebGLExtensions(_gl)
  16388. capabilities = new WebGLCapabilities(_gl, extensions, parameters)
  16389. extensions.init(capabilities)
  16390. utils = new WebGLUtils(_gl, extensions, capabilities)
  16391. state = new WebGLState(_gl, extensions, capabilities)
  16392. info = new WebGLInfo(_gl)
  16393. properties = new WebGLProperties()
  16394. textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info)
  16395. cubemaps = new WebGLCubeMaps(_this)
  16396. cubeuvmaps = new WebGLCubeUVMaps(_this)
  16397. attributes = new WebGLAttributes(_gl, capabilities)
  16398. bindingStates = new WebGLBindingStates(_gl, extensions, attributes, capabilities)
  16399. geometries = new WebGLGeometries(_gl, attributes, info, bindingStates)
  16400. objects = new WebGLObjects(_gl, geometries, attributes, info)
  16401. morphtargets = new WebGLMorphtargets(_gl, capabilities, textures)
  16402. clipping = new WebGLClipping(properties)
  16403. programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping)
  16404. materials = new WebGLMaterials(_this, properties)
  16405. renderLists = new WebGLRenderLists()
  16406. renderStates = new WebGLRenderStates(extensions, capabilities)
  16407. background = new WebGLBackground(_this, cubemaps, state, objects, _alpha, _premultipliedAlpha)
  16408. shadowMap = new WebGLShadowMap(_this, objects, capabilities)
  16409. bufferRenderer = new WebGLBufferRenderer(_gl, extensions, info, capabilities)
  16410. indexedBufferRenderer = new WebGLIndexedBufferRenderer(_gl, extensions, info, capabilities)
  16411. info.programs = programCache.programs
  16412. _this.capabilities = capabilities
  16413. _this.extensions = extensions
  16414. _this.properties = properties
  16415. _this.renderLists = renderLists
  16416. _this.shadowMap = shadowMap
  16417. _this.state = state
  16418. _this.info = info
  16419. }
  16420. initGLContext()
  16421. // xr
  16422. const xr = new WebXRManager(_this, _gl)
  16423. this.xr = xr
  16424. // API
  16425. this.getContext = function() {
  16426. return _gl
  16427. }
  16428. this.getContextAttributes = function() {
  16429. return _gl.getContextAttributes()
  16430. }
  16431. this.forceContextLoss = function() {
  16432. const extension = extensions.get('WEBGL_lose_context')
  16433. if (extension) extension.loseContext()
  16434. }
  16435. this.forceContextRestore = function() {
  16436. const extension = extensions.get('WEBGL_lose_context')
  16437. if (extension) extension.restoreContext()
  16438. }
  16439. this.getPixelRatio = function() {
  16440. return _pixelRatio
  16441. }
  16442. this.setPixelRatio = function(value) {
  16443. if (value === undefined) return
  16444. _pixelRatio = value
  16445. this.setSize(_width, _height, false)
  16446. }
  16447. this.getSize = function(target) {
  16448. return target.set(_width, _height)
  16449. }
  16450. this.setSize = function(width, height, updateStyle) {
  16451. if (xr.isPresenting) {
  16452. console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting.")
  16453. return
  16454. }
  16455. _width = width
  16456. _height = height
  16457. _canvas.width = Math.floor(width * _pixelRatio)
  16458. _canvas.height = Math.floor(height * _pixelRatio)
  16459. if (updateStyle !== false) {
  16460. _canvas.style.width = width + 'px'
  16461. _canvas.style.height = height + 'px'
  16462. }
  16463. this.setViewport(0, 0, width, height)
  16464. }
  16465. this.getDrawingBufferSize = function(target) {
  16466. return target.set(_width * _pixelRatio, _height * _pixelRatio).floor()
  16467. }
  16468. this.setDrawingBufferSize = function(width, height, pixelRatio) {
  16469. _width = width
  16470. _height = height
  16471. _pixelRatio = pixelRatio
  16472. _canvas.width = Math.floor(width * pixelRatio)
  16473. _canvas.height = Math.floor(height * pixelRatio)
  16474. this.setViewport(0, 0, width, height)
  16475. }
  16476. this.getCurrentViewport = function(target) {
  16477. return target.copy(_currentViewport)
  16478. }
  16479. this.getViewport = function(target) {
  16480. return target.copy(_viewport)
  16481. }
  16482. this.setViewport = function(x, y, width, height) {
  16483. if (x.isVector4) {
  16484. _viewport.set(x.x, x.y, x.z, x.w)
  16485. } else {
  16486. _viewport.set(x, y, width, height)
  16487. }
  16488. state.viewport(
  16489. _currentViewport
  16490. .copy(_viewport)
  16491. .multiplyScalar(_pixelRatio)
  16492. .floor()
  16493. )
  16494. }
  16495. this.getScissor = function(target) {
  16496. return target.copy(_scissor)
  16497. }
  16498. this.setScissor = function(x, y, width, height) {
  16499. if (x.isVector4) {
  16500. _scissor.set(x.x, x.y, x.z, x.w)
  16501. } else {
  16502. _scissor.set(x, y, width, height)
  16503. }
  16504. state.scissor(
  16505. _currentScissor
  16506. .copy(_scissor)
  16507. .multiplyScalar(_pixelRatio)
  16508. .floor()
  16509. )
  16510. }
  16511. this.getScissorTest = function() {
  16512. return _scissorTest
  16513. }
  16514. this.setScissorTest = function(boolean) {
  16515. state.setScissorTest((_scissorTest = boolean))
  16516. }
  16517. this.setOpaqueSort = function(method) {
  16518. _opaqueSort = method
  16519. }
  16520. this.setTransparentSort = function(method) {
  16521. _transparentSort = method
  16522. }
  16523. // Clearing
  16524. this.getClearColor = function(target) {
  16525. return target.copy(background.getClearColor())
  16526. }
  16527. this.setClearColor = function() {
  16528. background.setClearColor.apply(background, arguments)
  16529. }
  16530. this.getClearAlpha = function() {
  16531. return background.getClearAlpha()
  16532. }
  16533. this.setClearAlpha = function() {
  16534. background.setClearAlpha.apply(background, arguments)
  16535. }
  16536. this.clear = function(color = true, depth = true, stencil = true) {
  16537. let bits = 0
  16538. if (color) bits |= 16384
  16539. if (depth) bits |= 256
  16540. if (stencil) bits |= 1024
  16541. _gl.clear(bits)
  16542. }
  16543. this.clearColor = function() {
  16544. this.clear(true, false, false)
  16545. }
  16546. this.clearDepth = function() {
  16547. this.clear(false, true, false)
  16548. }
  16549. this.clearStencil = function() {
  16550. this.clear(false, false, true)
  16551. }
  16552. //
  16553. this.dispose = function() {
  16554. _canvas.removeEventListener('webglcontextlost', onContextLost, false)
  16555. _canvas.removeEventListener('webglcontextrestored', onContextRestore, false)
  16556. _canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false)
  16557. renderLists.dispose()
  16558. renderStates.dispose()
  16559. properties.dispose()
  16560. cubemaps.dispose()
  16561. cubeuvmaps.dispose()
  16562. objects.dispose()
  16563. bindingStates.dispose()
  16564. programCache.dispose()
  16565. xr.dispose()
  16566. xr.removeEventListener('sessionstart', onXRSessionStart)
  16567. xr.removeEventListener('sessionend', onXRSessionEnd)
  16568. if (_transmissionRenderTarget) {
  16569. _transmissionRenderTarget.dispose()
  16570. _transmissionRenderTarget = null
  16571. }
  16572. animation.stop()
  16573. }
  16574. // Events
  16575. function onContextLost(event) {
  16576. event.preventDefault()
  16577. console.log('THREE.WebGLRenderer: Context Lost.')
  16578. _isContextLost = true
  16579. }
  16580. function onContextRestore(/* event */) {
  16581. console.log('THREE.WebGLRenderer: Context Restored.')
  16582. _isContextLost = false
  16583. const infoAutoReset = info.autoReset
  16584. const shadowMapEnabled = shadowMap.enabled
  16585. const shadowMapAutoUpdate = shadowMap.autoUpdate
  16586. const shadowMapNeedsUpdate = shadowMap.needsUpdate
  16587. const shadowMapType = shadowMap.type
  16588. initGLContext()
  16589. info.autoReset = infoAutoReset
  16590. shadowMap.enabled = shadowMapEnabled
  16591. shadowMap.autoUpdate = shadowMapAutoUpdate
  16592. shadowMap.needsUpdate = shadowMapNeedsUpdate
  16593. shadowMap.type = shadowMapType
  16594. }
  16595. function onContextCreationError(event) {
  16596. console.error('THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage)
  16597. }
  16598. function onMaterialDispose(event) {
  16599. const material = event.target
  16600. material.removeEventListener('dispose', onMaterialDispose)
  16601. deallocateMaterial(material)
  16602. }
  16603. // Buffer deallocation
  16604. function deallocateMaterial(material) {
  16605. releaseMaterialProgramReferences(material)
  16606. properties.remove(material)
  16607. }
  16608. function releaseMaterialProgramReferences(material) {
  16609. const programs = properties.get(material).programs
  16610. if (programs !== undefined) {
  16611. programs.forEach(function(program) {
  16612. programCache.releaseProgram(program)
  16613. })
  16614. if (material.isShaderMaterial) {
  16615. programCache.releaseShaderCache(material)
  16616. }
  16617. }
  16618. }
  16619. // Buffer rendering
  16620. this.renderBufferDirect = function(camera, scene, geometry, material, object, group) {
  16621. if (scene === null) scene = _emptyScene // renderBufferDirect second parameter used to be fog (could be null)
  16622. const frontFaceCW = object.isMesh && object.matrixWorld.determinant() < 0
  16623. const program = setProgram(camera, scene, geometry, material, object)
  16624. state.setMaterial(material, frontFaceCW)
  16625. //
  16626. let index = geometry.index
  16627. const position = geometry.attributes.position
  16628. //
  16629. if (index === null) {
  16630. if (position === undefined || position.count === 0) return
  16631. } else if (index.count === 0) {
  16632. return
  16633. }
  16634. //
  16635. let rangeFactor = 1
  16636. if (material.wireframe === true) {
  16637. index = geometries.getWireframeAttribute(geometry)
  16638. rangeFactor = 2
  16639. }
  16640. bindingStates.setup(object, material, program, geometry, index)
  16641. let attribute
  16642. let renderer = bufferRenderer
  16643. if (index !== null) {
  16644. attribute = attributes.get(index)
  16645. renderer = indexedBufferRenderer
  16646. renderer.setIndex(attribute)
  16647. }
  16648. //
  16649. const dataCount = index !== null ? index.count : position.count
  16650. const rangeStart = geometry.drawRange.start * rangeFactor
  16651. const rangeCount = geometry.drawRange.count * rangeFactor
  16652. const groupStart = group !== null ? group.start * rangeFactor : 0
  16653. const groupCount = group !== null ? group.count * rangeFactor : Infinity
  16654. const drawStart = Math.max(rangeStart, groupStart)
  16655. const drawEnd = Math.min(dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1
  16656. const drawCount = Math.max(0, drawEnd - drawStart + 1)
  16657. if (drawCount === 0) return
  16658. //
  16659. if (object.isMesh) {
  16660. if (material.wireframe === true) {
  16661. state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio())
  16662. renderer.setMode(1)
  16663. } else {
  16664. renderer.setMode(4)
  16665. }
  16666. } else if (object.isLine) {
  16667. let lineWidth = material.linewidth
  16668. if (lineWidth === undefined) lineWidth = 1 // Not using Line*Material
  16669. state.setLineWidth(lineWidth * getTargetPixelRatio())
  16670. if (object.isLineSegments) {
  16671. renderer.setMode(1)
  16672. } else if (object.isLineLoop) {
  16673. renderer.setMode(2)
  16674. } else {
  16675. renderer.setMode(3)
  16676. }
  16677. } else if (object.isPoints) {
  16678. renderer.setMode(0)
  16679. } else if (object.isSprite) {
  16680. renderer.setMode(4)
  16681. }
  16682. if (object.isInstancedMesh) {
  16683. renderer.renderInstances(drawStart, drawCount, object.count)
  16684. } else if (geometry.isInstancedBufferGeometry) {
  16685. const instanceCount = Math.min(geometry.instanceCount, geometry._maxInstanceCount)
  16686. renderer.renderInstances(drawStart, drawCount, instanceCount)
  16687. } else {
  16688. renderer.render(drawStart, drawCount)
  16689. }
  16690. }
  16691. // Compile
  16692. this.compile = function(scene, camera) {
  16693. currentRenderState = renderStates.get(scene)
  16694. currentRenderState.init()
  16695. renderStateStack.push(currentRenderState)
  16696. scene.traverseVisible(function(object) {
  16697. if (object.isLight && object.layers.test(camera.layers)) {
  16698. currentRenderState.pushLight(object)
  16699. if (object.castShadow) {
  16700. currentRenderState.pushShadow(object)
  16701. }
  16702. }
  16703. })
  16704. currentRenderState.setupLights(_this.physicallyCorrectLights)
  16705. scene.traverse(function(object) {
  16706. const material = object.material
  16707. if (material) {
  16708. if (Array.isArray(material)) {
  16709. for (let i = 0; i < material.length; i++) {
  16710. const material2 = material[i]
  16711. getProgram(material2, scene, object)
  16712. }
  16713. } else {
  16714. getProgram(material, scene, object)
  16715. }
  16716. }
  16717. })
  16718. renderStateStack.pop()
  16719. currentRenderState = null
  16720. }
  16721. // Animation Loop
  16722. let onAnimationFrameCallback = null
  16723. function onAnimationFrame(time) {
  16724. if (onAnimationFrameCallback) onAnimationFrameCallback(time)
  16725. }
  16726. function onXRSessionStart() {
  16727. animation.stop()
  16728. }
  16729. function onXRSessionEnd() {
  16730. animation.start()
  16731. }
  16732. const animation = new WebGLAnimation()
  16733. animation.setAnimationLoop(onAnimationFrame)
  16734. if (typeof self !== 'undefined') animation.setContext(self)
  16735. this.setAnimationLoop = function(callback) {
  16736. onAnimationFrameCallback = callback
  16737. xr.setAnimationLoop(callback)
  16738. callback === null ? animation.stop() : animation.start()
  16739. }
  16740. xr.addEventListener('sessionstart', onXRSessionStart)
  16741. xr.addEventListener('sessionend', onXRSessionEnd)
  16742. // Rendering
  16743. this.render = function(scene, camera) {
  16744. if (camera !== undefined && camera.isCamera !== true) {
  16745. console.error('THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.')
  16746. return
  16747. }
  16748. if (_isContextLost === true) return
  16749. // update scene graph
  16750. if (scene.autoUpdate === true) scene.updateMatrixWorld()
  16751. // update camera matrices and frustum
  16752. if (camera.parent === null) camera.updateMatrixWorld()
  16753. if (xr.enabled === true && xr.isPresenting === true) {
  16754. if (xr.cameraAutoUpdate === true) xr.updateCamera(camera)
  16755. camera = xr.getCamera() // use XR camera for rendering
  16756. }
  16757. //
  16758. if (scene.isScene === true) scene.onBeforeRender(_this, scene, camera, _currentRenderTarget)
  16759. currentRenderState = renderStates.get(scene, renderStateStack.length)
  16760. currentRenderState.init()
  16761. renderStateStack.push(currentRenderState)
  16762. _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
  16763. _frustum.setFromProjectionMatrix(_projScreenMatrix)
  16764. _localClippingEnabled = this.localClippingEnabled
  16765. _clippingEnabled = clipping.init(this.clippingPlanes, _localClippingEnabled, camera)
  16766. currentRenderList = renderLists.get(scene, renderListStack.length)
  16767. currentRenderList.init()
  16768. renderListStack.push(currentRenderList)
  16769. projectObject(scene, camera, 0, _this.sortObjects)
  16770. currentRenderList.finish()
  16771. if (_this.sortObjects === true) {
  16772. currentRenderList.sort(_opaqueSort, _transparentSort)
  16773. }
  16774. //
  16775. if (_clippingEnabled === true) clipping.beginShadows()
  16776. const shadowsArray = currentRenderState.state.shadowsArray
  16777. shadowMap.render(shadowsArray, scene, camera)
  16778. if (_clippingEnabled === true) clipping.endShadows()
  16779. //
  16780. if (this.info.autoReset === true) this.info.reset()
  16781. //
  16782. background.render(currentRenderList, scene)
  16783. // render scene
  16784. currentRenderState.setupLights(_this.physicallyCorrectLights)
  16785. if (camera.isArrayCamera) {
  16786. const cameras = camera.cameras
  16787. for (let i = 0, l = cameras.length; i < l; i++) {
  16788. const camera2 = cameras[i]
  16789. renderScene(currentRenderList, scene, camera2, camera2.viewport)
  16790. }
  16791. } else {
  16792. renderScene(currentRenderList, scene, camera)
  16793. }
  16794. //
  16795. if (_currentRenderTarget !== null) {
  16796. // resolve multisample renderbuffers to a single-sample texture if necessary
  16797. textures.updateMultisampleRenderTarget(_currentRenderTarget)
  16798. // Generate mipmap if we're using any kind of mipmap filtering
  16799. textures.updateRenderTargetMipmap(_currentRenderTarget)
  16800. }
  16801. //
  16802. if (scene.isScene === true) scene.onAfterRender(_this, scene, camera)
  16803. // _gl.finish();
  16804. bindingStates.resetDefaultState()
  16805. _currentMaterialId = -1
  16806. _currentCamera = null
  16807. renderStateStack.pop()
  16808. if (renderStateStack.length > 0) {
  16809. currentRenderState = renderStateStack[renderStateStack.length - 1]
  16810. } else {
  16811. currentRenderState = null
  16812. }
  16813. renderListStack.pop()
  16814. if (renderListStack.length > 0) {
  16815. currentRenderList = renderListStack[renderListStack.length - 1]
  16816. } else {
  16817. currentRenderList = null
  16818. }
  16819. }
  16820. function projectObject(object, camera, groupOrder, sortObjects) {
  16821. if (object.visible === false) return
  16822. const visible = object.layers.test(camera.layers)
  16823. if (visible) {
  16824. if (object.isGroup) {
  16825. groupOrder = object.renderOrder
  16826. } else if (object.isLOD) {
  16827. if (object.autoUpdate === true) object.update(camera)
  16828. } else if (object.isLight) {
  16829. currentRenderState.pushLight(object)
  16830. if (object.castShadow) {
  16831. currentRenderState.pushShadow(object)
  16832. }
  16833. } else if (object.isSprite) {
  16834. if (!object.frustumCulled || _frustum.intersectsSprite(object)) {
  16835. if (sortObjects) {
  16836. _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix)
  16837. }
  16838. const geometry = objects.update(object)
  16839. const material = object.material
  16840. if (material.visible) {
  16841. currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null)
  16842. }
  16843. }
  16844. } else if (object.isMesh || object.isLine || object.isPoints) {
  16845. if (object.isSkinnedMesh) {
  16846. // update skeleton only once in a frame
  16847. if (object.skeleton.frame !== info.render.frame) {
  16848. object.skeleton.update()
  16849. object.skeleton.frame = info.render.frame
  16850. }
  16851. }
  16852. if (!object.frustumCulled || _frustum.intersectsObject(object)) {
  16853. if (sortObjects) {
  16854. _vector3.setFromMatrixPosition(object.matrixWorld).applyMatrix4(_projScreenMatrix)
  16855. }
  16856. const geometry = objects.update(object)
  16857. const material = object.material
  16858. if (Array.isArray(material)) {
  16859. const groups = geometry.groups
  16860. for (let i = 0, l = groups.length; i < l; i++) {
  16861. const group = groups[i]
  16862. const groupMaterial = material[group.materialIndex]
  16863. if (groupMaterial && groupMaterial.visible) {
  16864. currentRenderList.push(object, geometry, groupMaterial, groupOrder, _vector3.z, group)
  16865. }
  16866. }
  16867. } else if (material.visible) {
  16868. currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null)
  16869. }
  16870. }
  16871. }
  16872. }
  16873. const children = object.children
  16874. for (let i = 0, l = children.length; i < l; i++) {
  16875. projectObject(children[i], camera, groupOrder, sortObjects)
  16876. }
  16877. }
  16878. function renderScene(currentRenderList, scene, camera, viewport) {
  16879. const opaqueObjects = currentRenderList.opaque
  16880. const transmissiveObjects = currentRenderList.transmissive
  16881. const transparentObjects = currentRenderList.transparent
  16882. currentRenderState.setupLightsView(camera)
  16883. if (transmissiveObjects.length > 0) renderTransmissionPass(opaqueObjects, scene, camera)
  16884. if (viewport) state.viewport(_currentViewport.copy(viewport))
  16885. if (opaqueObjects.length > 0) renderObjects(opaqueObjects, scene, camera)
  16886. if (transmissiveObjects.length > 0) renderObjects(transmissiveObjects, scene, camera)
  16887. if (transparentObjects.length > 0) renderObjects(transparentObjects, scene, camera)
  16888. // Ensure depth buffer writing is enabled so it can be cleared on next render
  16889. state.buffers.depth.setTest(true)
  16890. state.buffers.depth.setMask(true)
  16891. state.buffers.color.setMask(true)
  16892. state.setPolygonOffset(false)
  16893. }
  16894. function renderTransmissionPass(opaqueObjects, scene, camera) {
  16895. const isWebGL2 = capabilities.isWebGL2
  16896. if (_transmissionRenderTarget === null) {
  16897. _transmissionRenderTarget = new WebGLRenderTarget(1, 1, {
  16898. generateMipmaps: true,
  16899. type: extensions.has('EXT_color_buffer_half_float') ? HalfFloatType : UnsignedByteType,
  16900. minFilter: LinearMipmapLinearFilter,
  16901. samples: isWebGL2 && _antialias === true ? 4 : 0
  16902. })
  16903. }
  16904. _this.getDrawingBufferSize(_vector2)
  16905. if (isWebGL2) {
  16906. _transmissionRenderTarget.setSize(_vector2.x, _vector2.y)
  16907. } else {
  16908. _transmissionRenderTarget.setSize(floorPowerOfTwo(_vector2.x), floorPowerOfTwo(_vector2.y))
  16909. }
  16910. //
  16911. const currentRenderTarget = _this.getRenderTarget()
  16912. _this.setRenderTarget(_transmissionRenderTarget)
  16913. _this.clear()
  16914. // Turn off the features which can affect the frag color for opaque objects pass.
  16915. // Otherwise they are applied twice in opaque objects pass and transmission objects pass.
  16916. const currentToneMapping = _this.toneMapping
  16917. _this.toneMapping = NoToneMapping
  16918. renderObjects(opaqueObjects, scene, camera)
  16919. _this.toneMapping = currentToneMapping
  16920. textures.updateMultisampleRenderTarget(_transmissionRenderTarget)
  16921. textures.updateRenderTargetMipmap(_transmissionRenderTarget)
  16922. _this.setRenderTarget(currentRenderTarget)
  16923. }
  16924. function renderObjects(renderList, scene, camera) {
  16925. const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null
  16926. for (let i = 0, l = renderList.length; i < l; i++) {
  16927. const renderItem = renderList[i]
  16928. const object = renderItem.object
  16929. const geometry = renderItem.geometry
  16930. const material = overrideMaterial === null ? renderItem.material : overrideMaterial
  16931. const group = renderItem.group
  16932. if (object.layers.test(camera.layers)) {
  16933. renderObject(object, scene, camera, geometry, material, group)
  16934. }
  16935. }
  16936. }
  16937. function renderObject(object, scene, camera, geometry, material, group) {
  16938. object.onBeforeRender(_this, scene, camera, geometry, material, group)
  16939. object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld)
  16940. object.normalMatrix.getNormalMatrix(object.modelViewMatrix)
  16941. material.onBeforeRender(_this, scene, camera, geometry, object, group)
  16942. if (material.transparent === true && material.side === DoubleSide) {
  16943. material.side = BackSide
  16944. material.needsUpdate = true
  16945. _this.renderBufferDirect(camera, scene, geometry, material, object, group)
  16946. material.side = FrontSide
  16947. material.needsUpdate = true
  16948. _this.renderBufferDirect(camera, scene, geometry, material, object, group)
  16949. material.side = DoubleSide
  16950. } else {
  16951. _this.renderBufferDirect(camera, scene, geometry, material, object, group)
  16952. }
  16953. object.onAfterRender(_this, scene, camera, geometry, material, group)
  16954. }
  16955. function getProgram(material, scene, object) {
  16956. if (scene.isScene !== true) scene = _emptyScene // scene could be a Mesh, Line, Points, ...
  16957. const materialProperties = properties.get(material)
  16958. const lights = currentRenderState.state.lights
  16959. const shadowsArray = currentRenderState.state.shadowsArray
  16960. const lightsStateVersion = lights.state.version
  16961. const parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object)
  16962. const programCacheKey = programCache.getProgramCacheKey(parameters)
  16963. let programs = materialProperties.programs
  16964. // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
  16965. materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null
  16966. materialProperties.fog = scene.fog
  16967. materialProperties.envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || materialProperties.environment)
  16968. if (programs === undefined) {
  16969. // new material
  16970. material.addEventListener('dispose', onMaterialDispose)
  16971. programs = new Map()
  16972. materialProperties.programs = programs
  16973. }
  16974. let program = programs.get(programCacheKey)
  16975. if (program !== undefined) {
  16976. // early out if program and light state is identical
  16977. if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) {
  16978. updateCommonMaterialProperties(material, parameters)
  16979. return program
  16980. }
  16981. } else {
  16982. parameters.uniforms = programCache.getUniforms(material)
  16983. material.onBuild(object, parameters, _this)
  16984. material.onBeforeCompile(parameters, _this)
  16985. program = programCache.acquireProgram(parameters, programCacheKey)
  16986. programs.set(programCacheKey, program)
  16987. materialProperties.uniforms = parameters.uniforms
  16988. }
  16989. const uniforms = materialProperties.uniforms
  16990. if ((!material.isShaderMaterial && !material.isRawShaderMaterial) || material.clipping === true) {
  16991. uniforms.clippingPlanes = clipping.uniform
  16992. }
  16993. updateCommonMaterialProperties(material, parameters)
  16994. // store the light setup it was created for
  16995. materialProperties.needsLights = materialNeedsLights(material)
  16996. materialProperties.lightsStateVersion = lightsStateVersion
  16997. if (materialProperties.needsLights) {
  16998. // wire up the material to this renderer's lighting state
  16999. uniforms.ambientLightColor.value = lights.state.ambient
  17000. uniforms.lightProbe.value = lights.state.probe
  17001. uniforms.directionalLights.value = lights.state.directional
  17002. uniforms.directionalLightShadows.value = lights.state.directionalShadow
  17003. uniforms.spotLights.value = lights.state.spot
  17004. uniforms.spotLightShadows.value = lights.state.spotShadow
  17005. uniforms.rectAreaLights.value = lights.state.rectArea
  17006. uniforms.ltc_1.value = lights.state.rectAreaLTC1
  17007. uniforms.ltc_2.value = lights.state.rectAreaLTC2
  17008. uniforms.pointLights.value = lights.state.point
  17009. uniforms.pointLightShadows.value = lights.state.pointShadow
  17010. uniforms.hemisphereLights.value = lights.state.hemi
  17011. uniforms.directionalShadowMap.value = lights.state.directionalShadowMap
  17012. uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix
  17013. uniforms.spotShadowMap.value = lights.state.spotShadowMap
  17014. uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix
  17015. uniforms.pointShadowMap.value = lights.state.pointShadowMap
  17016. uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix
  17017. // TODO (abelnation): add area lights shadow info to uniforms
  17018. }
  17019. const progUniforms = program.getUniforms()
  17020. const uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, uniforms)
  17021. materialProperties.currentProgram = program
  17022. materialProperties.uniformsList = uniformsList
  17023. return program
  17024. }
  17025. function updateCommonMaterialProperties(material, parameters) {
  17026. const materialProperties = properties.get(material)
  17027. materialProperties.outputEncoding = parameters.outputEncoding
  17028. materialProperties.instancing = parameters.instancing
  17029. materialProperties.skinning = parameters.skinning
  17030. materialProperties.morphTargets = parameters.morphTargets
  17031. materialProperties.morphNormals = parameters.morphNormals
  17032. materialProperties.morphColors = parameters.morphColors
  17033. materialProperties.morphTargetsCount = parameters.morphTargetsCount
  17034. materialProperties.numClippingPlanes = parameters.numClippingPlanes
  17035. materialProperties.numIntersection = parameters.numClipIntersection
  17036. materialProperties.vertexAlphas = parameters.vertexAlphas
  17037. materialProperties.vertexTangents = parameters.vertexTangents
  17038. materialProperties.toneMapping = parameters.toneMapping
  17039. }
  17040. function setProgram(camera, scene, geometry, material, object) {
  17041. if (scene.isScene !== true) scene = _emptyScene // scene could be a Mesh, Line, Points, ...
  17042. textures.resetTextureUnits()
  17043. const fog = scene.fog
  17044. const environment = material.isMeshStandardMaterial ? scene.environment : null
  17045. const encoding = _currentRenderTarget === null ? _this.outputEncoding : _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding
  17046. const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment)
  17047. const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4
  17048. const vertexTangents = !!material.normalMap && !!geometry.attributes.tangent
  17049. const morphTargets = !!geometry.morphAttributes.position
  17050. const morphNormals = !!geometry.morphAttributes.normal
  17051. const morphColors = !!geometry.morphAttributes.color
  17052. const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping
  17053. const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color
  17054. const morphTargetsCount = morphAttribute !== undefined ? morphAttribute.length : 0
  17055. const materialProperties = properties.get(material)
  17056. const lights = currentRenderState.state.lights
  17057. if (_clippingEnabled === true) {
  17058. if (_localClippingEnabled === true || camera !== _currentCamera) {
  17059. const useCache = camera === _currentCamera && material.id === _currentMaterialId
  17060. // we might want to call this function with some ClippingGroup
  17061. // object instead of the material, once it becomes feasible
  17062. // (#8465, #8379)
  17063. clipping.setState(material, camera, useCache)
  17064. }
  17065. }
  17066. //
  17067. let needsProgramChange = false
  17068. if (material.version === materialProperties.__version) {
  17069. if (materialProperties.needsLights && materialProperties.lightsStateVersion !== lights.state.version) {
  17070. needsProgramChange = true
  17071. } else if (materialProperties.outputEncoding !== encoding) {
  17072. needsProgramChange = true
  17073. } else if (object.isInstancedMesh && materialProperties.instancing === false) {
  17074. needsProgramChange = true
  17075. } else if (!object.isInstancedMesh && materialProperties.instancing === true) {
  17076. needsProgramChange = true
  17077. } else if (object.isSkinnedMesh && materialProperties.skinning === false) {
  17078. needsProgramChange = true
  17079. } else if (!object.isSkinnedMesh && materialProperties.skinning === true) {
  17080. needsProgramChange = true
  17081. } else if (materialProperties.envMap !== envMap) {
  17082. needsProgramChange = true
  17083. } else if (material.fog === true && materialProperties.fog !== fog) {
  17084. needsProgramChange = true
  17085. } else if (
  17086. materialProperties.numClippingPlanes !== undefined &&
  17087. (materialProperties.numClippingPlanes !== clipping.numPlanes || materialProperties.numIntersection !== clipping.numIntersection)
  17088. ) {
  17089. needsProgramChange = true
  17090. } else if (materialProperties.vertexAlphas !== vertexAlphas) {
  17091. needsProgramChange = true
  17092. } else if (materialProperties.vertexTangents !== vertexTangents) {
  17093. needsProgramChange = true
  17094. } else if (materialProperties.morphTargets !== morphTargets) {
  17095. needsProgramChange = true
  17096. } else if (materialProperties.morphNormals !== morphNormals) {
  17097. needsProgramChange = true
  17098. } else if (materialProperties.morphColors !== morphColors) {
  17099. needsProgramChange = true
  17100. } else if (materialProperties.toneMapping !== toneMapping) {
  17101. needsProgramChange = true
  17102. } else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) {
  17103. needsProgramChange = true
  17104. }
  17105. } else {
  17106. needsProgramChange = true
  17107. materialProperties.__version = material.version
  17108. }
  17109. //
  17110. let program = materialProperties.currentProgram
  17111. if (needsProgramChange === true) {
  17112. program = getProgram(material, scene, object)
  17113. }
  17114. let refreshProgram = false
  17115. let refreshMaterial = false
  17116. let refreshLights = false
  17117. const p_uniforms = program.getUniforms(),
  17118. m_uniforms = materialProperties.uniforms
  17119. if (state.useProgram(program.program)) {
  17120. refreshProgram = true
  17121. refreshMaterial = true
  17122. refreshLights = true
  17123. }
  17124. if (material.id !== _currentMaterialId) {
  17125. _currentMaterialId = material.id
  17126. refreshMaterial = true
  17127. }
  17128. if (refreshProgram || _currentCamera !== camera) {
  17129. p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix)
  17130. if (capabilities.logarithmicDepthBuffer) {
  17131. p_uniforms.setValue(_gl, 'logDepthBufFC', 2.0 / (Math.log(camera.far + 1.0) / Math.LN2))
  17132. }
  17133. if (_currentCamera !== camera) {
  17134. _currentCamera = camera
  17135. // lighting uniforms depend on the camera so enforce an update
  17136. // now, in case this material supports lights - or later, when
  17137. // the next material that does gets activated:
  17138. refreshMaterial = true // set to true on material change
  17139. refreshLights = true // remains set until update done
  17140. }
  17141. // load material specific uniforms
  17142. // (shader material also gets them for the sake of genericity)
  17143. if (material.isShaderMaterial || material.isMeshPhongMaterial || material.isMeshToonMaterial || material.isMeshStandardMaterial || material.envMap) {
  17144. const uCamPos = p_uniforms.map.cameraPosition
  17145. if (uCamPos !== undefined) {
  17146. uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld))
  17147. }
  17148. }
  17149. if (
  17150. material.isMeshPhongMaterial ||
  17151. material.isMeshToonMaterial ||
  17152. material.isMeshLambertMaterial ||
  17153. material.isMeshBasicMaterial ||
  17154. material.isMeshStandardMaterial ||
  17155. material.isShaderMaterial
  17156. ) {
  17157. p_uniforms.setValue(_gl, 'isOrthographic', camera.isOrthographicCamera === true)
  17158. }
  17159. if (
  17160. material.isMeshPhongMaterial ||
  17161. material.isMeshToonMaterial ||
  17162. material.isMeshLambertMaterial ||
  17163. material.isMeshBasicMaterial ||
  17164. material.isMeshStandardMaterial ||
  17165. material.isShaderMaterial ||
  17166. material.isShadowMaterial ||
  17167. object.isSkinnedMesh
  17168. ) {
  17169. p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse)
  17170. }
  17171. }
  17172. // skinning and morph target uniforms must be set even if material didn't change
  17173. // auto-setting of texture unit for bone and morph texture must go before other textures
  17174. // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
  17175. if (object.isSkinnedMesh) {
  17176. p_uniforms.setOptional(_gl, object, 'bindMatrix')
  17177. p_uniforms.setOptional(_gl, object, 'bindMatrixInverse')
  17178. const skeleton = object.skeleton
  17179. if (skeleton) {
  17180. if (capabilities.floatVertexTextures) {
  17181. if (skeleton.boneTexture === null) skeleton.computeBoneTexture()
  17182. p_uniforms.setValue(_gl, 'boneTexture', skeleton.boneTexture, textures)
  17183. p_uniforms.setValue(_gl, 'boneTextureSize', skeleton.boneTextureSize)
  17184. } else {
  17185. console.warn('THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.')
  17186. }
  17187. }
  17188. }
  17189. const morphAttributes = geometry.morphAttributes
  17190. if (morphAttributes.position !== undefined || morphAttributes.normal !== undefined || (morphAttributes.color !== undefined && capabilities.isWebGL2 === true)) {
  17191. morphtargets.update(object, geometry, material, program)
  17192. }
  17193. if (refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow) {
  17194. materialProperties.receiveShadow = object.receiveShadow
  17195. p_uniforms.setValue(_gl, 'receiveShadow', object.receiveShadow)
  17196. }
  17197. if (refreshMaterial) {
  17198. p_uniforms.setValue(_gl, 'toneMappingExposure', _this.toneMappingExposure)
  17199. if (materialProperties.needsLights) {
  17200. // the current material requires lighting info
  17201. // note: all lighting uniforms are always set correctly
  17202. // they simply reference the renderer's state for their
  17203. // values
  17204. //
  17205. // use the current material's .needsUpdate flags to set
  17206. // the GL state when required
  17207. markUniformsLightsNeedsUpdate(m_uniforms, refreshLights)
  17208. }
  17209. // refresh uniforms common to several materials
  17210. if (fog && material.fog === true) {
  17211. materials.refreshFogUniforms(m_uniforms, fog)
  17212. }
  17213. materials.refreshMaterialUniforms(m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget)
  17214. WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures)
  17215. }
  17216. if (material.isShaderMaterial && material.uniformsNeedUpdate === true) {
  17217. WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, textures)
  17218. material.uniformsNeedUpdate = false
  17219. }
  17220. if (material.isSpriteMaterial) {
  17221. p_uniforms.setValue(_gl, 'center', object.center)
  17222. }
  17223. // common matrices
  17224. p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix)
  17225. p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix)
  17226. p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld)
  17227. return program
  17228. }
  17229. // If uniforms are marked as clean, they don't need to be loaded to the GPU.
  17230. function markUniformsLightsNeedsUpdate(uniforms, value) {
  17231. uniforms.ambientLightColor.needsUpdate = value
  17232. uniforms.lightProbe.needsUpdate = value
  17233. uniforms.directionalLights.needsUpdate = value
  17234. uniforms.directionalLightShadows.needsUpdate = value
  17235. uniforms.pointLights.needsUpdate = value
  17236. uniforms.pointLightShadows.needsUpdate = value
  17237. uniforms.spotLights.needsUpdate = value
  17238. uniforms.spotLightShadows.needsUpdate = value
  17239. uniforms.rectAreaLights.needsUpdate = value
  17240. uniforms.hemisphereLights.needsUpdate = value
  17241. }
  17242. function materialNeedsLights(material) {
  17243. return (
  17244. material.isMeshLambertMaterial ||
  17245. material.isMeshToonMaterial ||
  17246. material.isMeshPhongMaterial ||
  17247. material.isMeshStandardMaterial ||
  17248. material.isShadowMaterial ||
  17249. (material.isShaderMaterial && material.lights === true)
  17250. )
  17251. }
  17252. this.getActiveCubeFace = function() {
  17253. return _currentActiveCubeFace
  17254. }
  17255. this.getActiveMipmapLevel = function() {
  17256. return _currentActiveMipmapLevel
  17257. }
  17258. this.getRenderTarget = function() {
  17259. return _currentRenderTarget
  17260. }
  17261. this.setRenderTargetTextures = function(renderTarget, colorTexture, depthTexture) {
  17262. properties.get(renderTarget.texture).__webglTexture = colorTexture
  17263. properties.get(renderTarget.depthTexture).__webglTexture = depthTexture
  17264. const renderTargetProperties = properties.get(renderTarget)
  17265. renderTargetProperties.__hasExternalTextures = true
  17266. if (renderTargetProperties.__hasExternalTextures) {
  17267. renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined
  17268. if (!renderTargetProperties.__autoAllocateDepthBuffer) {
  17269. // The multisample_render_to_texture extension doesn't work properly if there
  17270. // are midframe flushes and an external depth buffer. Disable use of the extension.
  17271. if (extensions.has('WEBGL_multisampled_render_to_texture') === true) {
  17272. console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided')
  17273. renderTargetProperties.__useRenderToTexture = false
  17274. }
  17275. }
  17276. }
  17277. }
  17278. this.setRenderTargetFramebuffer = function(renderTarget, defaultFramebuffer) {
  17279. const renderTargetProperties = properties.get(renderTarget)
  17280. renderTargetProperties.__webglFramebuffer = defaultFramebuffer
  17281. renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined
  17282. }
  17283. this.setRenderTarget = function(renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) {
  17284. _currentRenderTarget = renderTarget
  17285. _currentActiveCubeFace = activeCubeFace
  17286. _currentActiveMipmapLevel = activeMipmapLevel
  17287. let useDefaultFramebuffer = true
  17288. if (renderTarget) {
  17289. const renderTargetProperties = properties.get(renderTarget)
  17290. if (renderTargetProperties.__useDefaultFramebuffer !== undefined) {
  17291. // We need to make sure to rebind the framebuffer.
  17292. state.bindFramebuffer(36160, null)
  17293. useDefaultFramebuffer = false
  17294. } else if (renderTargetProperties.__webglFramebuffer === undefined) {
  17295. textures.setupRenderTarget(renderTarget)
  17296. } else if (renderTargetProperties.__hasExternalTextures) {
  17297. // Color and depth texture must be rebound in order for the swapchain to update.
  17298. textures.rebindTextures(renderTarget, properties.get(renderTarget.texture).__webglTexture, properties.get(renderTarget.depthTexture).__webglTexture)
  17299. }
  17300. }
  17301. let framebuffer = null
  17302. let isCube = false
  17303. let isRenderTarget3D = false
  17304. if (renderTarget) {
  17305. const texture = renderTarget.texture
  17306. if (texture.isData3DTexture || texture.isDataArrayTexture) {
  17307. isRenderTarget3D = true
  17308. }
  17309. const __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer
  17310. if (renderTarget.isWebGLCubeRenderTarget) {
  17311. framebuffer = __webglFramebuffer[activeCubeFace]
  17312. isCube = true
  17313. } else if (capabilities.isWebGL2 && renderTarget.samples > 0 && textures.useMultisampledRTT(renderTarget) === false) {
  17314. framebuffer = properties.get(renderTarget).__webglMultisampledFramebuffer
  17315. } else {
  17316. framebuffer = __webglFramebuffer
  17317. }
  17318. _currentViewport.copy(renderTarget.viewport)
  17319. _currentScissor.copy(renderTarget.scissor)
  17320. _currentScissorTest = renderTarget.scissorTest
  17321. } else {
  17322. _currentViewport
  17323. .copy(_viewport)
  17324. .multiplyScalar(_pixelRatio)
  17325. .floor()
  17326. _currentScissor
  17327. .copy(_scissor)
  17328. .multiplyScalar(_pixelRatio)
  17329. .floor()
  17330. _currentScissorTest = _scissorTest
  17331. }
  17332. const framebufferBound = state.bindFramebuffer(36160, framebuffer)
  17333. if (framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer) {
  17334. state.drawBuffers(renderTarget, framebuffer)
  17335. }
  17336. state.viewport(_currentViewport)
  17337. state.scissor(_currentScissor)
  17338. state.setScissorTest(_currentScissorTest)
  17339. if (isCube) {
  17340. const textureProperties = properties.get(renderTarget.texture)
  17341. _gl.framebufferTexture2D(36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel)
  17342. } else if (isRenderTarget3D) {
  17343. const textureProperties = properties.get(renderTarget.texture)
  17344. const layer = activeCubeFace || 0
  17345. _gl.framebufferTextureLayer(36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer)
  17346. }
  17347. _currentMaterialId = -1 // reset current material to ensure correct uniform bindings
  17348. }
  17349. this.readRenderTargetPixels = function(renderTarget, x, y, width, height, buffer, activeCubeFaceIndex) {
  17350. if (!(renderTarget && renderTarget.isWebGLRenderTarget)) {
  17351. console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.')
  17352. return
  17353. }
  17354. let framebuffer = properties.get(renderTarget).__webglFramebuffer
  17355. if (renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined) {
  17356. framebuffer = framebuffer[activeCubeFaceIndex]
  17357. }
  17358. if (framebuffer) {
  17359. state.bindFramebuffer(36160, framebuffer)
  17360. try {
  17361. const texture = renderTarget.texture
  17362. const textureFormat = texture.format
  17363. const textureType = texture.type
  17364. if (textureFormat !== RGBAFormat && utils.convert(textureFormat) !== _gl.getParameter(35739)) {
  17365. console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.')
  17366. return
  17367. }
  17368. const halfFloatSupportedByExt = textureType === HalfFloatType && (extensions.has('EXT_color_buffer_half_float') || (capabilities.isWebGL2 && extensions.has('EXT_color_buffer_float')))
  17369. if (
  17370. textureType !== UnsignedByteType &&
  17371. utils.convert(textureType) !== _gl.getParameter(35738) && // Edge and Chrome Mac < 52 (#9513)
  17372. !(textureType === FloatType && (capabilities.isWebGL2 || extensions.has('OES_texture_float') || extensions.has('WEBGL_color_buffer_float'))) && // Chrome Mac >= 52 and Firefox
  17373. !halfFloatSupportedByExt
  17374. ) {
  17375. console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.')
  17376. return
  17377. }
  17378. // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
  17379. if (x >= 0 && x <= renderTarget.width - width && y >= 0 && y <= renderTarget.height - height) {
  17380. _gl.readPixels(x, y, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer)
  17381. }
  17382. } finally {
  17383. // restore framebuffer of current render target if necessary
  17384. const framebuffer = _currentRenderTarget !== null ? properties.get(_currentRenderTarget).__webglFramebuffer : null
  17385. state.bindFramebuffer(36160, framebuffer)
  17386. }
  17387. }
  17388. }
  17389. this.copyFramebufferToTexture = function(position, texture, level = 0) {
  17390. const levelScale = Math.pow(2, -level)
  17391. const width = Math.floor(texture.image.width * levelScale)
  17392. const height = Math.floor(texture.image.height * levelScale)
  17393. textures.setTexture2D(texture, 0)
  17394. _gl.copyTexSubImage2D(3553, level, 0, 0, position.x, position.y, width, height)
  17395. state.unbindTexture()
  17396. }
  17397. this.copyTextureToTexture = function(position, srcTexture, dstTexture, level = 0) {
  17398. const width = srcTexture.image.width
  17399. const height = srcTexture.image.height
  17400. const glFormat = utils.convert(dstTexture.format)
  17401. const glType = utils.convert(dstTexture.type)
  17402. textures.setTexture2D(dstTexture, 0)
  17403. // As another texture upload may have changed pixelStorei
  17404. // parameters, make sure they are correct for the dstTexture
  17405. _gl.pixelStorei(37440, dstTexture.flipY)
  17406. _gl.pixelStorei(37441, dstTexture.premultiplyAlpha)
  17407. _gl.pixelStorei(3317, dstTexture.unpackAlignment)
  17408. if (srcTexture.isDataTexture) {
  17409. _gl.texSubImage2D(3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data)
  17410. } else {
  17411. if (srcTexture.isCompressedTexture) {
  17412. _gl.compressedTexSubImage2D(3553, level, position.x, position.y, srcTexture.mipmaps[0].width, srcTexture.mipmaps[0].height, glFormat, srcTexture.mipmaps[0].data)
  17413. } else {
  17414. _gl.texSubImage2D(3553, level, position.x, position.y, glFormat, glType, srcTexture.image)
  17415. }
  17416. }
  17417. // Generate mipmaps only when copying level 0
  17418. if (level === 0 && dstTexture.generateMipmaps) _gl.generateMipmap(3553)
  17419. state.unbindTexture()
  17420. }
  17421. this.copyTextureToTexture3D = function(sourceBox, position, srcTexture, dstTexture, level = 0) {
  17422. if (_this.isWebGL1Renderer) {
  17423. console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.')
  17424. return
  17425. }
  17426. const width = sourceBox.max.x - sourceBox.min.x + 1
  17427. const height = sourceBox.max.y - sourceBox.min.y + 1
  17428. const depth = sourceBox.max.z - sourceBox.min.z + 1
  17429. const glFormat = utils.convert(dstTexture.format)
  17430. const glType = utils.convert(dstTexture.type)
  17431. let glTarget
  17432. if (dstTexture.isData3DTexture) {
  17433. textures.setTexture3D(dstTexture, 0)
  17434. glTarget = 32879
  17435. } else if (dstTexture.isDataArrayTexture) {
  17436. textures.setTexture2DArray(dstTexture, 0)
  17437. glTarget = 35866
  17438. } else {
  17439. console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.')
  17440. return
  17441. }
  17442. _gl.pixelStorei(37440, dstTexture.flipY)
  17443. _gl.pixelStorei(37441, dstTexture.premultiplyAlpha)
  17444. _gl.pixelStorei(3317, dstTexture.unpackAlignment)
  17445. const unpackRowLen = _gl.getParameter(3314)
  17446. const unpackImageHeight = _gl.getParameter(32878)
  17447. const unpackSkipPixels = _gl.getParameter(3316)
  17448. const unpackSkipRows = _gl.getParameter(3315)
  17449. const unpackSkipImages = _gl.getParameter(32877)
  17450. const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[0] : srcTexture.image
  17451. _gl.pixelStorei(3314, image.width)
  17452. _gl.pixelStorei(32878, image.height)
  17453. _gl.pixelStorei(3316, sourceBox.min.x)
  17454. _gl.pixelStorei(3315, sourceBox.min.y)
  17455. _gl.pixelStorei(32877, sourceBox.min.z)
  17456. if (srcTexture.isDataTexture || srcTexture.isData3DTexture) {
  17457. _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data)
  17458. } else {
  17459. if (srcTexture.isCompressedTexture) {
  17460. console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.')
  17461. _gl.compressedTexSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data)
  17462. } else {
  17463. _gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image)
  17464. }
  17465. }
  17466. _gl.pixelStorei(3314, unpackRowLen)
  17467. _gl.pixelStorei(32878, unpackImageHeight)
  17468. _gl.pixelStorei(3316, unpackSkipPixels)
  17469. _gl.pixelStorei(3315, unpackSkipRows)
  17470. _gl.pixelStorei(32877, unpackSkipImages)
  17471. // Generate mipmaps only when copying level 0
  17472. if (level === 0 && dstTexture.generateMipmaps) _gl.generateMipmap(glTarget)
  17473. state.unbindTexture()
  17474. }
  17475. this.initTexture = function(texture) {
  17476. textures.setTexture2D(texture, 0)
  17477. state.unbindTexture()
  17478. }
  17479. this.resetState = function() {
  17480. _currentActiveCubeFace = 0
  17481. _currentActiveMipmapLevel = 0
  17482. _currentRenderTarget = null
  17483. state.reset()
  17484. bindingStates.reset()
  17485. }
  17486. if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
  17487. __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe', { detail: this }))
  17488. }
  17489. }
  17490. class WebGL1Renderer extends WebGLRenderer {}
  17491. WebGL1Renderer.prototype.isWebGL1Renderer = true
  17492. class FogExp2 {
  17493. constructor(color, density = 0.00025) {
  17494. this.isFogExp2 = true
  17495. this.name = ''
  17496. this.color = new Color(color)
  17497. this.density = density
  17498. }
  17499. clone() {
  17500. return new FogExp2(this.color, this.density)
  17501. }
  17502. toJSON(/* meta */) {
  17503. return {
  17504. type: 'FogExp2',
  17505. color: this.color.getHex(),
  17506. density: this.density
  17507. }
  17508. }
  17509. }
  17510. class Fog {
  17511. constructor(color, near = 1, far = 1000) {
  17512. this.isFog = true
  17513. this.name = ''
  17514. this.color = new Color(color)
  17515. this.near = near
  17516. this.far = far
  17517. }
  17518. clone() {
  17519. return new Fog(this.color, this.near, this.far)
  17520. }
  17521. toJSON(/* meta */) {
  17522. return {
  17523. type: 'Fog',
  17524. color: this.color.getHex(),
  17525. near: this.near,
  17526. far: this.far
  17527. }
  17528. }
  17529. }
  17530. class Scene extends Object3D {
  17531. constructor() {
  17532. super()
  17533. this.isScene = true
  17534. this.type = 'Scene'
  17535. this.background = null
  17536. this.environment = null
  17537. this.fog = null
  17538. this.overrideMaterial = null
  17539. this.autoUpdate = true // checked by the renderer
  17540. if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
  17541. __THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe', { detail: this }))
  17542. }
  17543. }
  17544. copy(source, recursive) {
  17545. super.copy(source, recursive)
  17546. if (source.background !== null) this.background = source.background.clone()
  17547. if (source.environment !== null) this.environment = source.environment.clone()
  17548. if (source.fog !== null) this.fog = source.fog.clone()
  17549. if (source.overrideMaterial !== null) this.overrideMaterial = source.overrideMaterial.clone()
  17550. this.autoUpdate = source.autoUpdate
  17551. this.matrixAutoUpdate = source.matrixAutoUpdate
  17552. return this
  17553. }
  17554. toJSON(meta) {
  17555. const data = super.toJSON(meta)
  17556. if (this.fog !== null) data.object.fog = this.fog.toJSON()
  17557. return data
  17558. }
  17559. }
  17560. class InterleavedBuffer {
  17561. constructor(array, stride) {
  17562. this.isInterleavedBuffer = true
  17563. this.array = array
  17564. this.stride = stride
  17565. this.count = array !== undefined ? array.length / stride : 0
  17566. this.usage = StaticDrawUsage
  17567. this.updateRange = { offset: 0, count: -1 }
  17568. this.version = 0
  17569. this.uuid = generateUUID()
  17570. }
  17571. onUploadCallback() {}
  17572. set needsUpdate(value) {
  17573. if (value === true) this.version++
  17574. }
  17575. setUsage(value) {
  17576. this.usage = value
  17577. return this
  17578. }
  17579. copy(source) {
  17580. this.array = new source.array.constructor(source.array)
  17581. this.count = source.count
  17582. this.stride = source.stride
  17583. this.usage = source.usage
  17584. return this
  17585. }
  17586. copyAt(index1, attribute, index2) {
  17587. index1 *= this.stride
  17588. index2 *= attribute.stride
  17589. for (let i = 0, l = this.stride; i < l; i++) {
  17590. this.array[index1 + i] = attribute.array[index2 + i]
  17591. }
  17592. return this
  17593. }
  17594. set(value, offset = 0) {
  17595. this.array.set(value, offset)
  17596. return this
  17597. }
  17598. clone(data) {
  17599. if (data.arrayBuffers === undefined) {
  17600. data.arrayBuffers = {}
  17601. }
  17602. if (this.array.buffer._uuid === undefined) {
  17603. this.array.buffer._uuid = generateUUID()
  17604. }
  17605. if (data.arrayBuffers[this.array.buffer._uuid] === undefined) {
  17606. data.arrayBuffers[this.array.buffer._uuid] = this.array.slice(0).buffer
  17607. }
  17608. const array = new this.array.constructor(data.arrayBuffers[this.array.buffer._uuid])
  17609. const ib = new this.constructor(array, this.stride)
  17610. ib.setUsage(this.usage)
  17611. return ib
  17612. }
  17613. onUpload(callback) {
  17614. this.onUploadCallback = callback
  17615. return this
  17616. }
  17617. toJSON(data) {
  17618. if (data.arrayBuffers === undefined) {
  17619. data.arrayBuffers = {}
  17620. }
  17621. // generate UUID for array buffer if necessary
  17622. if (this.array.buffer._uuid === undefined) {
  17623. this.array.buffer._uuid = generateUUID()
  17624. }
  17625. if (data.arrayBuffers[this.array.buffer._uuid] === undefined) {
  17626. data.arrayBuffers[this.array.buffer._uuid] = Array.prototype.slice.call(new Uint32Array(this.array.buffer))
  17627. }
  17628. //
  17629. return {
  17630. uuid: this.uuid,
  17631. buffer: this.array.buffer._uuid,
  17632. type: this.array.constructor.name,
  17633. stride: this.stride
  17634. }
  17635. }
  17636. }
  17637. const _vector$6 = /*@__PURE__*/ new Vector3()
  17638. class InterleavedBufferAttribute {
  17639. constructor(interleavedBuffer, itemSize, offset, normalized = false) {
  17640. this.isInterleavedBufferAttribute = true
  17641. this.name = ''
  17642. this.data = interleavedBuffer
  17643. this.itemSize = itemSize
  17644. this.offset = offset
  17645. this.normalized = normalized === true
  17646. }
  17647. get count() {
  17648. return this.data.count
  17649. }
  17650. get array() {
  17651. return this.data.array
  17652. }
  17653. set needsUpdate(value) {
  17654. this.data.needsUpdate = value
  17655. }
  17656. applyMatrix4(m) {
  17657. for (let i = 0, l = this.data.count; i < l; i++) {
  17658. _vector$6.fromBufferAttribute(this, i)
  17659. _vector$6.applyMatrix4(m)
  17660. this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z)
  17661. }
  17662. return this
  17663. }
  17664. applyNormalMatrix(m) {
  17665. for (let i = 0, l = this.count; i < l; i++) {
  17666. _vector$6.fromBufferAttribute(this, i)
  17667. _vector$6.applyNormalMatrix(m)
  17668. this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z)
  17669. }
  17670. return this
  17671. }
  17672. transformDirection(m) {
  17673. for (let i = 0, l = this.count; i < l; i++) {
  17674. _vector$6.fromBufferAttribute(this, i)
  17675. _vector$6.transformDirection(m)
  17676. this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z)
  17677. }
  17678. return this
  17679. }
  17680. setX(index, x) {
  17681. this.data.array[index * this.data.stride + this.offset] = x
  17682. return this
  17683. }
  17684. setY(index, y) {
  17685. this.data.array[index * this.data.stride + this.offset + 1] = y
  17686. return this
  17687. }
  17688. setZ(index, z) {
  17689. this.data.array[index * this.data.stride + this.offset + 2] = z
  17690. return this
  17691. }
  17692. setW(index, w) {
  17693. this.data.array[index * this.data.stride + this.offset + 3] = w
  17694. return this
  17695. }
  17696. getX(index) {
  17697. return this.data.array[index * this.data.stride + this.offset]
  17698. }
  17699. getY(index) {
  17700. return this.data.array[index * this.data.stride + this.offset + 1]
  17701. }
  17702. getZ(index) {
  17703. return this.data.array[index * this.data.stride + this.offset + 2]
  17704. }
  17705. getW(index) {
  17706. return this.data.array[index * this.data.stride + this.offset + 3]
  17707. }
  17708. setXY(index, x, y) {
  17709. index = index * this.data.stride + this.offset
  17710. this.data.array[index + 0] = x
  17711. this.data.array[index + 1] = y
  17712. return this
  17713. }
  17714. setXYZ(index, x, y, z) {
  17715. index = index * this.data.stride + this.offset
  17716. this.data.array[index + 0] = x
  17717. this.data.array[index + 1] = y
  17718. this.data.array[index + 2] = z
  17719. return this
  17720. }
  17721. setXYZW(index, x, y, z, w) {
  17722. index = index * this.data.stride + this.offset
  17723. this.data.array[index + 0] = x
  17724. this.data.array[index + 1] = y
  17725. this.data.array[index + 2] = z
  17726. this.data.array[index + 3] = w
  17727. return this
  17728. }
  17729. clone(data) {
  17730. if (data === undefined) {
  17731. console.log('THREE.InterleavedBufferAttribute.clone(): Cloning an interlaved buffer attribute will deinterleave buffer data.')
  17732. const array = []
  17733. for (let i = 0; i < this.count; i++) {
  17734. const index = i * this.data.stride + this.offset
  17735. for (let j = 0; j < this.itemSize; j++) {
  17736. array.push(this.data.array[index + j])
  17737. }
  17738. }
  17739. return new BufferAttribute(new this.array.constructor(array), this.itemSize, this.normalized)
  17740. } else {
  17741. if (data.interleavedBuffers === undefined) {
  17742. data.interleavedBuffers = {}
  17743. }
  17744. if (data.interleavedBuffers[this.data.uuid] === undefined) {
  17745. data.interleavedBuffers[this.data.uuid] = this.data.clone(data)
  17746. }
  17747. return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized)
  17748. }
  17749. }
  17750. toJSON(data) {
  17751. if (data === undefined) {
  17752. console.log('THREE.InterleavedBufferAttribute.toJSON(): Serializing an interlaved buffer attribute will deinterleave buffer data.')
  17753. const array = []
  17754. for (let i = 0; i < this.count; i++) {
  17755. const index = i * this.data.stride + this.offset
  17756. for (let j = 0; j < this.itemSize; j++) {
  17757. array.push(this.data.array[index + j])
  17758. }
  17759. }
  17760. // deinterleave data and save it as an ordinary buffer attribute for now
  17761. return {
  17762. itemSize: this.itemSize,
  17763. type: this.array.constructor.name,
  17764. array: array,
  17765. normalized: this.normalized
  17766. }
  17767. } else {
  17768. // save as true interlaved attribtue
  17769. if (data.interleavedBuffers === undefined) {
  17770. data.interleavedBuffers = {}
  17771. }
  17772. if (data.interleavedBuffers[this.data.uuid] === undefined) {
  17773. data.interleavedBuffers[this.data.uuid] = this.data.toJSON(data)
  17774. }
  17775. return {
  17776. isInterleavedBufferAttribute: true,
  17777. itemSize: this.itemSize,
  17778. data: this.data.uuid,
  17779. offset: this.offset,
  17780. normalized: this.normalized
  17781. }
  17782. }
  17783. }
  17784. }
  17785. class SpriteMaterial extends Material {
  17786. constructor(parameters) {
  17787. super()
  17788. this.isSpriteMaterial = true
  17789. this.type = 'SpriteMaterial'
  17790. this.color = new Color(0xffffff)
  17791. this.map = null
  17792. this.alphaMap = null
  17793. this.rotation = 0
  17794. this.sizeAttenuation = true
  17795. this.transparent = true
  17796. this.fog = true
  17797. this.setValues(parameters)
  17798. }
  17799. copy(source) {
  17800. super.copy(source)
  17801. this.color.copy(source.color)
  17802. this.map = source.map
  17803. this.alphaMap = source.alphaMap
  17804. this.rotation = source.rotation
  17805. this.sizeAttenuation = source.sizeAttenuation
  17806. this.fog = source.fog
  17807. return this
  17808. }
  17809. }
  17810. let _geometry
  17811. const _intersectPoint = /*@__PURE__*/ new Vector3()
  17812. const _worldScale = /*@__PURE__*/ new Vector3()
  17813. const _mvPosition = /*@__PURE__*/ new Vector3()
  17814. const _alignedPosition = /*@__PURE__*/ new Vector2()
  17815. const _rotatedPosition = /*@__PURE__*/ new Vector2()
  17816. const _viewWorldMatrix = /*@__PURE__*/ new Matrix4()
  17817. const _vA = /*@__PURE__*/ new Vector3()
  17818. const _vB = /*@__PURE__*/ new Vector3()
  17819. const _vC = /*@__PURE__*/ new Vector3()
  17820. const _uvA = /*@__PURE__*/ new Vector2()
  17821. const _uvB = /*@__PURE__*/ new Vector2()
  17822. const _uvC = /*@__PURE__*/ new Vector2()
  17823. class Sprite extends Object3D {
  17824. constructor(material) {
  17825. super()
  17826. this.isSprite = true
  17827. this.type = 'Sprite'
  17828. if (_geometry === undefined) {
  17829. _geometry = new BufferGeometry()
  17830. const float32Array = new Float32Array([-0.5, -0.5, 0, 0, 0, 0.5, -0.5, 0, 1, 0, 0.5, 0.5, 0, 1, 1, -0.5, 0.5, 0, 0, 1])
  17831. const interleavedBuffer = new InterleavedBuffer(float32Array, 5)
  17832. _geometry.setIndex([0, 1, 2, 0, 2, 3])
  17833. _geometry.setAttribute('position', new InterleavedBufferAttribute(interleavedBuffer, 3, 0, false))
  17834. _geometry.setAttribute('uv', new InterleavedBufferAttribute(interleavedBuffer, 2, 3, false))
  17835. }
  17836. this.geometry = _geometry
  17837. this.material = material !== undefined ? material : new SpriteMaterial()
  17838. this.center = new Vector2(0.5, 0.5)
  17839. }
  17840. raycast(raycaster, intersects) {
  17841. if (raycaster.camera === null) {
  17842. console.error('THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.')
  17843. }
  17844. _worldScale.setFromMatrixScale(this.matrixWorld)
  17845. _viewWorldMatrix.copy(raycaster.camera.matrixWorld)
  17846. this.modelViewMatrix.multiplyMatrices(raycaster.camera.matrixWorldInverse, this.matrixWorld)
  17847. _mvPosition.setFromMatrixPosition(this.modelViewMatrix)
  17848. if (raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false) {
  17849. _worldScale.multiplyScalar(-_mvPosition.z)
  17850. }
  17851. const rotation = this.material.rotation
  17852. let sin, cos
  17853. if (rotation !== 0) {
  17854. cos = Math.cos(rotation)
  17855. sin = Math.sin(rotation)
  17856. }
  17857. const center = this.center
  17858. transformVertex(_vA.set(-0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos)
  17859. transformVertex(_vB.set(0.5, -0.5, 0), _mvPosition, center, _worldScale, sin, cos)
  17860. transformVertex(_vC.set(0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos)
  17861. _uvA.set(0, 0)
  17862. _uvB.set(1, 0)
  17863. _uvC.set(1, 1)
  17864. // check first triangle
  17865. let intersect = raycaster.ray.intersectTriangle(_vA, _vB, _vC, false, _intersectPoint)
  17866. if (intersect === null) {
  17867. // check second triangle
  17868. transformVertex(_vB.set(-0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos)
  17869. _uvB.set(0, 1)
  17870. intersect = raycaster.ray.intersectTriangle(_vA, _vC, _vB, false, _intersectPoint)
  17871. if (intersect === null) {
  17872. return
  17873. }
  17874. }
  17875. const distance = raycaster.ray.origin.distanceTo(_intersectPoint)
  17876. if (distance < raycaster.near || distance > raycaster.far) return
  17877. intersects.push({
  17878. distance: distance,
  17879. point: _intersectPoint.clone(),
  17880. uv: Triangle.getUV(_intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2()),
  17881. face: null,
  17882. object: this
  17883. })
  17884. }
  17885. copy(source, recursive) {
  17886. super.copy(source, recursive)
  17887. if (source.center !== undefined) this.center.copy(source.center)
  17888. this.material = source.material
  17889. return this
  17890. }
  17891. }
  17892. function transformVertex(vertexPosition, mvPosition, center, scale, sin, cos) {
  17893. // compute position in camera space
  17894. _alignedPosition
  17895. .subVectors(vertexPosition, center)
  17896. .addScalar(0.5)
  17897. .multiply(scale)
  17898. // to check if rotation is not zero
  17899. if (sin !== undefined) {
  17900. _rotatedPosition.x = cos * _alignedPosition.x - sin * _alignedPosition.y
  17901. _rotatedPosition.y = sin * _alignedPosition.x + cos * _alignedPosition.y
  17902. } else {
  17903. _rotatedPosition.copy(_alignedPosition)
  17904. }
  17905. vertexPosition.copy(mvPosition)
  17906. vertexPosition.x += _rotatedPosition.x
  17907. vertexPosition.y += _rotatedPosition.y
  17908. // transform to world space
  17909. vertexPosition.applyMatrix4(_viewWorldMatrix)
  17910. }
  17911. const _v1$2 = /*@__PURE__*/ new Vector3()
  17912. const _v2$1 = /*@__PURE__*/ new Vector3()
  17913. class LOD extends Object3D {
  17914. constructor() {
  17915. super()
  17916. this._currentLevel = 0
  17917. this.type = 'LOD'
  17918. Object.defineProperties(this, {
  17919. levels: {
  17920. enumerable: true,
  17921. value: []
  17922. },
  17923. isLOD: {
  17924. value: true
  17925. }
  17926. })
  17927. this.autoUpdate = true
  17928. }
  17929. copy(source) {
  17930. super.copy(source, false)
  17931. const levels = source.levels
  17932. for (let i = 0, l = levels.length; i < l; i++) {
  17933. const level = levels[i]
  17934. this.addLevel(level.object.clone(), level.distance)
  17935. }
  17936. this.autoUpdate = source.autoUpdate
  17937. return this
  17938. }
  17939. addLevel(object, distance = 0) {
  17940. distance = Math.abs(distance)
  17941. const levels = this.levels
  17942. let l
  17943. for (l = 0; l < levels.length; l++) {
  17944. if (distance < levels[l].distance) {
  17945. break
  17946. }
  17947. }
  17948. levels.splice(l, 0, { distance: distance, object: object })
  17949. this.add(object)
  17950. return this
  17951. }
  17952. getCurrentLevel() {
  17953. return this._currentLevel
  17954. }
  17955. getObjectForDistance(distance) {
  17956. const levels = this.levels
  17957. if (levels.length > 0) {
  17958. let i, l
  17959. for (i = 1, l = levels.length; i < l; i++) {
  17960. if (distance < levels[i].distance) {
  17961. break
  17962. }
  17963. }
  17964. return levels[i - 1].object
  17965. }
  17966. return null
  17967. }
  17968. raycast(raycaster, intersects) {
  17969. const levels = this.levels
  17970. if (levels.length > 0) {
  17971. _v1$2.setFromMatrixPosition(this.matrixWorld)
  17972. const distance = raycaster.ray.origin.distanceTo(_v1$2)
  17973. this.getObjectForDistance(distance).raycast(raycaster, intersects)
  17974. }
  17975. }
  17976. update(camera) {
  17977. const levels = this.levels
  17978. if (levels.length > 1) {
  17979. _v1$2.setFromMatrixPosition(camera.matrixWorld)
  17980. _v2$1.setFromMatrixPosition(this.matrixWorld)
  17981. const distance = _v1$2.distanceTo(_v2$1) / camera.zoom
  17982. levels[0].object.visible = true
  17983. let i, l
  17984. for (i = 1, l = levels.length; i < l; i++) {
  17985. if (distance >= levels[i].distance) {
  17986. levels[i - 1].object.visible = false
  17987. levels[i].object.visible = true
  17988. } else {
  17989. break
  17990. }
  17991. }
  17992. this._currentLevel = i - 1
  17993. for (; i < l; i++) {
  17994. levels[i].object.visible = false
  17995. }
  17996. }
  17997. }
  17998. toJSON(meta) {
  17999. const data = super.toJSON(meta)
  18000. if (this.autoUpdate === false) data.object.autoUpdate = false
  18001. data.object.levels = []
  18002. const levels = this.levels
  18003. for (let i = 0, l = levels.length; i < l; i++) {
  18004. const level = levels[i]
  18005. data.object.levels.push({
  18006. object: level.object.uuid,
  18007. distance: level.distance
  18008. })
  18009. }
  18010. return data
  18011. }
  18012. }
  18013. const _basePosition = /*@__PURE__*/ new Vector3()
  18014. const _skinIndex = /*@__PURE__*/ new Vector4()
  18015. const _skinWeight = /*@__PURE__*/ new Vector4()
  18016. const _vector$5 = /*@__PURE__*/ new Vector3()
  18017. const _matrix = /*@__PURE__*/ new Matrix4()
  18018. class SkinnedMesh extends Mesh {
  18019. constructor(geometry, material) {
  18020. super(geometry, material)
  18021. this.isSkinnedMesh = true
  18022. this.type = 'SkinnedMesh'
  18023. this.bindMode = 'attached'
  18024. this.bindMatrix = new Matrix4()
  18025. this.bindMatrixInverse = new Matrix4()
  18026. }
  18027. copy(source, recursive) {
  18028. super.copy(source, recursive)
  18029. this.bindMode = source.bindMode
  18030. this.bindMatrix.copy(source.bindMatrix)
  18031. this.bindMatrixInverse.copy(source.bindMatrixInverse)
  18032. this.skeleton = source.skeleton
  18033. return this
  18034. }
  18035. bind(skeleton, bindMatrix) {
  18036. this.skeleton = skeleton
  18037. if (bindMatrix === undefined) {
  18038. this.updateMatrixWorld(true)
  18039. this.skeleton.calculateInverses()
  18040. bindMatrix = this.matrixWorld
  18041. }
  18042. this.bindMatrix.copy(bindMatrix)
  18043. this.bindMatrixInverse.copy(bindMatrix).invert()
  18044. }
  18045. pose() {
  18046. this.skeleton.pose()
  18047. }
  18048. normalizeSkinWeights() {
  18049. const vector = new Vector4()
  18050. const skinWeight = this.geometry.attributes.skinWeight
  18051. for (let i = 0, l = skinWeight.count; i < l; i++) {
  18052. vector.fromBufferAttribute(skinWeight, i)
  18053. const scale = 1.0 / vector.manhattanLength()
  18054. if (scale !== Infinity) {
  18055. vector.multiplyScalar(scale)
  18056. } else {
  18057. vector.set(1, 0, 0, 0) // do something reasonable
  18058. }
  18059. skinWeight.setXYZW(i, vector.x, vector.y, vector.z, vector.w)
  18060. }
  18061. }
  18062. updateMatrixWorld(force) {
  18063. super.updateMatrixWorld(force)
  18064. if (this.bindMode === 'attached') {
  18065. this.bindMatrixInverse.copy(this.matrixWorld).invert()
  18066. } else if (this.bindMode === 'detached') {
  18067. this.bindMatrixInverse.copy(this.bindMatrix).invert()
  18068. } else {
  18069. console.warn('THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode)
  18070. }
  18071. }
  18072. boneTransform(index, target) {
  18073. const skeleton = this.skeleton
  18074. const geometry = this.geometry
  18075. _skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index)
  18076. _skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index)
  18077. _basePosition.copy(target).applyMatrix4(this.bindMatrix)
  18078. target.set(0, 0, 0)
  18079. for (let i = 0; i < 4; i++) {
  18080. const weight = _skinWeight.getComponent(i)
  18081. if (weight !== 0) {
  18082. const boneIndex = _skinIndex.getComponent(i)
  18083. _matrix.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex])
  18084. target.addScaledVector(_vector$5.copy(_basePosition).applyMatrix4(_matrix), weight)
  18085. }
  18086. }
  18087. return target.applyMatrix4(this.bindMatrixInverse)
  18088. }
  18089. }
  18090. class Bone extends Object3D {
  18091. constructor() {
  18092. super()
  18093. this.isBone = true
  18094. this.type = 'Bone'
  18095. }
  18096. }
  18097. class DataTexture extends Texture {
  18098. constructor(data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding) {
  18099. super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding)
  18100. this.isDataTexture = true
  18101. this.image = { data: data, width: width, height: height }
  18102. this.generateMipmaps = false
  18103. this.flipY = false
  18104. this.unpackAlignment = 1
  18105. }
  18106. }
  18107. const _offsetMatrix = /*@__PURE__*/ new Matrix4()
  18108. const _identityMatrix = /*@__PURE__*/ new Matrix4()
  18109. class Skeleton {
  18110. constructor(bones = [], boneInverses = []) {
  18111. this.uuid = generateUUID()
  18112. this.bones = bones.slice(0)
  18113. this.boneInverses = boneInverses
  18114. this.boneMatrices = null
  18115. this.boneTexture = null
  18116. this.boneTextureSize = 0
  18117. this.frame = -1
  18118. this.init()
  18119. }
  18120. init() {
  18121. const bones = this.bones
  18122. const boneInverses = this.boneInverses
  18123. this.boneMatrices = new Float32Array(bones.length * 16)
  18124. // calculate inverse bone matrices if necessary
  18125. if (boneInverses.length === 0) {
  18126. this.calculateInverses()
  18127. } else {
  18128. // handle special case
  18129. if (bones.length !== boneInverses.length) {
  18130. console.warn('THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.')
  18131. this.boneInverses = []
  18132. for (let i = 0, il = this.bones.length; i < il; i++) {
  18133. this.boneInverses.push(new Matrix4())
  18134. }
  18135. }
  18136. }
  18137. }
  18138. calculateInverses() {
  18139. this.boneInverses.length = 0
  18140. for (let i = 0, il = this.bones.length; i < il; i++) {
  18141. const inverse = new Matrix4()
  18142. if (this.bones[i]) {
  18143. inverse.copy(this.bones[i].matrixWorld).invert()
  18144. }
  18145. this.boneInverses.push(inverse)
  18146. }
  18147. }
  18148. pose() {
  18149. // recover the bind-time world matrices
  18150. for (let i = 0, il = this.bones.length; i < il; i++) {
  18151. const bone = this.bones[i]
  18152. if (bone) {
  18153. bone.matrixWorld.copy(this.boneInverses[i]).invert()
  18154. }
  18155. }
  18156. // compute the local matrices, positions, rotations and scales
  18157. for (let i = 0, il = this.bones.length; i < il; i++) {
  18158. const bone = this.bones[i]
  18159. if (bone) {
  18160. if (bone.parent && bone.parent.isBone) {
  18161. bone.matrix.copy(bone.parent.matrixWorld).invert()
  18162. bone.matrix.multiply(bone.matrixWorld)
  18163. } else {
  18164. bone.matrix.copy(bone.matrixWorld)
  18165. }
  18166. bone.matrix.decompose(bone.position, bone.quaternion, bone.scale)
  18167. }
  18168. }
  18169. }
  18170. update() {
  18171. const bones = this.bones
  18172. const boneInverses = this.boneInverses
  18173. const boneMatrices = this.boneMatrices
  18174. const boneTexture = this.boneTexture
  18175. // flatten bone matrices to array
  18176. for (let i = 0, il = bones.length; i < il; i++) {
  18177. // compute the offset between the current and the original transform
  18178. const matrix = bones[i] ? bones[i].matrixWorld : _identityMatrix
  18179. _offsetMatrix.multiplyMatrices(matrix, boneInverses[i])
  18180. _offsetMatrix.toArray(boneMatrices, i * 16)
  18181. }
  18182. if (boneTexture !== null) {
  18183. boneTexture.needsUpdate = true
  18184. }
  18185. }
  18186. clone() {
  18187. return new Skeleton(this.bones, this.boneInverses)
  18188. }
  18189. computeBoneTexture() {
  18190. // layout (1 matrix = 4 pixels)
  18191. // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
  18192. // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
  18193. // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
  18194. // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
  18195. // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
  18196. let size = Math.sqrt(this.bones.length * 4) // 4 pixels needed for 1 matrix
  18197. size = ceilPowerOfTwo(size)
  18198. size = Math.max(size, 4)
  18199. const boneMatrices = new Float32Array(size * size * 4) // 4 floats per RGBA pixel
  18200. boneMatrices.set(this.boneMatrices) // copy current values
  18201. const boneTexture = new DataTexture(boneMatrices, size, size, RGBAFormat, FloatType)
  18202. boneTexture.needsUpdate = true
  18203. this.boneMatrices = boneMatrices
  18204. this.boneTexture = boneTexture
  18205. this.boneTextureSize = size
  18206. return this
  18207. }
  18208. getBoneByName(name) {
  18209. for (let i = 0, il = this.bones.length; i < il; i++) {
  18210. const bone = this.bones[i]
  18211. if (bone.name === name) {
  18212. return bone
  18213. }
  18214. }
  18215. return undefined
  18216. }
  18217. dispose() {
  18218. if (this.boneTexture !== null) {
  18219. this.boneTexture.dispose()
  18220. this.boneTexture = null
  18221. }
  18222. }
  18223. fromJSON(json, bones) {
  18224. this.uuid = json.uuid
  18225. for (let i = 0, l = json.bones.length; i < l; i++) {
  18226. const uuid = json.bones[i]
  18227. let bone = bones[uuid]
  18228. if (bone === undefined) {
  18229. console.warn('THREE.Skeleton: No bone found with UUID:', uuid)
  18230. bone = new Bone()
  18231. }
  18232. this.bones.push(bone)
  18233. this.boneInverses.push(new Matrix4().fromArray(json.boneInverses[i]))
  18234. }
  18235. this.init()
  18236. return this
  18237. }
  18238. toJSON() {
  18239. const data = {
  18240. metadata: {
  18241. version: 4.5,
  18242. type: 'Skeleton',
  18243. generator: 'Skeleton.toJSON'
  18244. },
  18245. bones: [],
  18246. boneInverses: []
  18247. }
  18248. data.uuid = this.uuid
  18249. const bones = this.bones
  18250. const boneInverses = this.boneInverses
  18251. for (let i = 0, l = bones.length; i < l; i++) {
  18252. const bone = bones[i]
  18253. data.bones.push(bone.uuid)
  18254. const boneInverse = boneInverses[i]
  18255. data.boneInverses.push(boneInverse.toArray())
  18256. }
  18257. return data
  18258. }
  18259. }
  18260. class InstancedBufferAttribute extends BufferAttribute {
  18261. constructor(array, itemSize, normalized, meshPerAttribute = 1) {
  18262. if (typeof normalized === 'number') {
  18263. meshPerAttribute = normalized
  18264. normalized = false
  18265. console.error('THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.')
  18266. }
  18267. super(array, itemSize, normalized)
  18268. this.isInstancedBufferAttribute = true
  18269. this.meshPerAttribute = meshPerAttribute
  18270. }
  18271. copy(source) {
  18272. super.copy(source)
  18273. this.meshPerAttribute = source.meshPerAttribute
  18274. return this
  18275. }
  18276. toJSON() {
  18277. const data = super.toJSON()
  18278. data.meshPerAttribute = this.meshPerAttribute
  18279. data.isInstancedBufferAttribute = true
  18280. return data
  18281. }
  18282. }
  18283. const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4()
  18284. const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4()
  18285. const _instanceIntersects = []
  18286. const _mesh = /*@__PURE__*/ new Mesh()
  18287. class InstancedMesh extends Mesh {
  18288. constructor(geometry, material, count) {
  18289. super(geometry, material)
  18290. this.isInstancedMesh = true
  18291. this.instanceMatrix = new InstancedBufferAttribute(new Float32Array(count * 16), 16)
  18292. this.instanceColor = null
  18293. this.count = count
  18294. this.frustumCulled = false
  18295. }
  18296. copy(source, recursive) {
  18297. super.copy(source, recursive)
  18298. this.instanceMatrix.copy(source.instanceMatrix)
  18299. if (source.instanceColor !== null) this.instanceColor = source.instanceColor.clone()
  18300. this.count = source.count
  18301. return this
  18302. }
  18303. getColorAt(index, color) {
  18304. color.fromArray(this.instanceColor.array, index * 3)
  18305. }
  18306. getMatrixAt(index, matrix) {
  18307. matrix.fromArray(this.instanceMatrix.array, index * 16)
  18308. }
  18309. raycast(raycaster, intersects) {
  18310. const matrixWorld = this.matrixWorld
  18311. const raycastTimes = this.count
  18312. _mesh.geometry = this.geometry
  18313. _mesh.material = this.material
  18314. if (_mesh.material === undefined) return
  18315. for (let instanceId = 0; instanceId < raycastTimes; instanceId++) {
  18316. // calculate the world matrix for each instance
  18317. this.getMatrixAt(instanceId, _instanceLocalMatrix)
  18318. _instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix)
  18319. // the mesh represents this single instance
  18320. _mesh.matrixWorld = _instanceWorldMatrix
  18321. _mesh.raycast(raycaster, _instanceIntersects)
  18322. // process the result of raycast
  18323. for (let i = 0, l = _instanceIntersects.length; i < l; i++) {
  18324. const intersect = _instanceIntersects[i]
  18325. intersect.instanceId = instanceId
  18326. intersect.object = this
  18327. intersects.push(intersect)
  18328. }
  18329. _instanceIntersects.length = 0
  18330. }
  18331. }
  18332. setColorAt(index, color) {
  18333. if (this.instanceColor === null) {
  18334. this.instanceColor = new InstancedBufferAttribute(new Float32Array(this.instanceMatrix.count * 3), 3)
  18335. }
  18336. color.toArray(this.instanceColor.array, index * 3)
  18337. }
  18338. setMatrixAt(index, matrix) {
  18339. matrix.toArray(this.instanceMatrix.array, index * 16)
  18340. }
  18341. updateMorphTargets() {}
  18342. dispose() {
  18343. this.dispatchEvent({ type: 'dispose' })
  18344. }
  18345. }
  18346. class LineBasicMaterial extends Material {
  18347. constructor(parameters) {
  18348. super()
  18349. this.isLineBasicMaterial = true
  18350. this.type = 'LineBasicMaterial'
  18351. this.color = new Color(0xffffff)
  18352. this.linewidth = 1
  18353. this.linecap = 'round'
  18354. this.linejoin = 'round'
  18355. this.fog = true
  18356. this.setValues(parameters)
  18357. }
  18358. copy(source) {
  18359. super.copy(source)
  18360. this.color.copy(source.color)
  18361. this.linewidth = source.linewidth
  18362. this.linecap = source.linecap
  18363. this.linejoin = source.linejoin
  18364. this.fog = source.fog
  18365. return this
  18366. }
  18367. }
  18368. const _start$1 = /*@__PURE__*/ new Vector3()
  18369. const _end$1 = /*@__PURE__*/ new Vector3()
  18370. const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4()
  18371. const _ray$1 = /*@__PURE__*/ new Ray()
  18372. const _sphere$1 = /*@__PURE__*/ new Sphere()
  18373. class Line extends Object3D {
  18374. constructor(geometry = new BufferGeometry(), material = new LineBasicMaterial()) {
  18375. super()
  18376. this.isLine = true
  18377. this.type = 'Line'
  18378. this.geometry = geometry
  18379. this.material = material
  18380. this.updateMorphTargets()
  18381. }
  18382. copy(source, recursive) {
  18383. super.copy(source, recursive)
  18384. this.material = source.material
  18385. this.geometry = source.geometry
  18386. return this
  18387. }
  18388. computeLineDistances() {
  18389. const geometry = this.geometry
  18390. // we assume non-indexed geometry
  18391. if (geometry.index === null) {
  18392. const positionAttribute = geometry.attributes.position
  18393. const lineDistances = [0]
  18394. for (let i = 1, l = positionAttribute.count; i < l; i++) {
  18395. _start$1.fromBufferAttribute(positionAttribute, i - 1)
  18396. _end$1.fromBufferAttribute(positionAttribute, i)
  18397. lineDistances[i] = lineDistances[i - 1]
  18398. lineDistances[i] += _start$1.distanceTo(_end$1)
  18399. }
  18400. geometry.setAttribute('lineDistance', new Float32BufferAttribute(lineDistances, 1))
  18401. } else {
  18402. console.warn('THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.')
  18403. }
  18404. return this
  18405. }
  18406. raycast(raycaster, intersects) {
  18407. const geometry = this.geometry
  18408. const matrixWorld = this.matrixWorld
  18409. const threshold = raycaster.params.Line.threshold
  18410. const drawRange = geometry.drawRange
  18411. // Checking boundingSphere distance to ray
  18412. if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
  18413. _sphere$1.copy(geometry.boundingSphere)
  18414. _sphere$1.applyMatrix4(matrixWorld)
  18415. _sphere$1.radius += threshold
  18416. if (raycaster.ray.intersectsSphere(_sphere$1) === false) return
  18417. //
  18418. _inverseMatrix$1.copy(matrixWorld).invert()
  18419. _ray$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$1)
  18420. const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3)
  18421. const localThresholdSq = localThreshold * localThreshold
  18422. const vStart = new Vector3()
  18423. const vEnd = new Vector3()
  18424. const interSegment = new Vector3()
  18425. const interRay = new Vector3()
  18426. const step = this.isLineSegments ? 2 : 1
  18427. const index = geometry.index
  18428. const attributes = geometry.attributes
  18429. const positionAttribute = attributes.position
  18430. if (index !== null) {
  18431. const start = Math.max(0, drawRange.start)
  18432. const end = Math.min(index.count, drawRange.start + drawRange.count)
  18433. for (let i = start, l = end - 1; i < l; i += step) {
  18434. const a = index.getX(i)
  18435. const b = index.getX(i + 1)
  18436. vStart.fromBufferAttribute(positionAttribute, a)
  18437. vEnd.fromBufferAttribute(positionAttribute, b)
  18438. const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment)
  18439. if (distSq > localThresholdSq) continue
  18440. interRay.applyMatrix4(this.matrixWorld) //Move back to world space for distance calculation
  18441. const distance = raycaster.ray.origin.distanceTo(interRay)
  18442. if (distance < raycaster.near || distance > raycaster.far) continue
  18443. intersects.push({
  18444. distance: distance,
  18445. // What do we want? intersection point on the ray or on the segment??
  18446. // point: raycaster.ray.at( distance ),
  18447. point: interSegment.clone().applyMatrix4(this.matrixWorld),
  18448. index: i,
  18449. face: null,
  18450. faceIndex: null,
  18451. object: this
  18452. })
  18453. }
  18454. } else {
  18455. const start = Math.max(0, drawRange.start)
  18456. const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count)
  18457. for (let i = start, l = end - 1; i < l; i += step) {
  18458. vStart.fromBufferAttribute(positionAttribute, i)
  18459. vEnd.fromBufferAttribute(positionAttribute, i + 1)
  18460. const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment)
  18461. if (distSq > localThresholdSq) continue
  18462. interRay.applyMatrix4(this.matrixWorld) //Move back to world space for distance calculation
  18463. const distance = raycaster.ray.origin.distanceTo(interRay)
  18464. if (distance < raycaster.near || distance > raycaster.far) continue
  18465. intersects.push({
  18466. distance: distance,
  18467. // What do we want? intersection point on the ray or on the segment??
  18468. // point: raycaster.ray.at( distance ),
  18469. point: interSegment.clone().applyMatrix4(this.matrixWorld),
  18470. index: i,
  18471. face: null,
  18472. faceIndex: null,
  18473. object: this
  18474. })
  18475. }
  18476. }
  18477. }
  18478. updateMorphTargets() {
  18479. const geometry = this.geometry
  18480. const morphAttributes = geometry.morphAttributes
  18481. const keys = Object.keys(morphAttributes)
  18482. if (keys.length > 0) {
  18483. const morphAttribute = morphAttributes[keys[0]]
  18484. if (morphAttribute !== undefined) {
  18485. this.morphTargetInfluences = []
  18486. this.morphTargetDictionary = {}
  18487. for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
  18488. const name = morphAttribute[m].name || String(m)
  18489. this.morphTargetInfluences.push(0)
  18490. this.morphTargetDictionary[name] = m
  18491. }
  18492. }
  18493. }
  18494. }
  18495. }
  18496. const _start = /*@__PURE__*/ new Vector3()
  18497. const _end = /*@__PURE__*/ new Vector3()
  18498. class LineSegments extends Line {
  18499. constructor(geometry, material) {
  18500. super(geometry, material)
  18501. this.isLineSegments = true
  18502. this.type = 'LineSegments'
  18503. }
  18504. computeLineDistances() {
  18505. const geometry = this.geometry
  18506. // we assume non-indexed geometry
  18507. if (geometry.index === null) {
  18508. const positionAttribute = geometry.attributes.position
  18509. const lineDistances = []
  18510. for (let i = 0, l = positionAttribute.count; i < l; i += 2) {
  18511. _start.fromBufferAttribute(positionAttribute, i)
  18512. _end.fromBufferAttribute(positionAttribute, i + 1)
  18513. lineDistances[i] = i === 0 ? 0 : lineDistances[i - 1]
  18514. lineDistances[i + 1] = lineDistances[i] + _start.distanceTo(_end)
  18515. }
  18516. geometry.setAttribute('lineDistance', new Float32BufferAttribute(lineDistances, 1))
  18517. } else {
  18518. console.warn('THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.')
  18519. }
  18520. return this
  18521. }
  18522. }
  18523. class LineLoop extends Line {
  18524. constructor(geometry, material) {
  18525. super(geometry, material)
  18526. this.isLineLoop = true
  18527. this.type = 'LineLoop'
  18528. }
  18529. }
  18530. class PointsMaterial extends Material {
  18531. constructor(parameters) {
  18532. super()
  18533. this.isPointsMaterial = true
  18534. this.type = 'PointsMaterial'
  18535. this.color = new Color(0xffffff)
  18536. this.map = null
  18537. this.alphaMap = null
  18538. this.size = 1
  18539. this.sizeAttenuation = true
  18540. this.fog = true
  18541. this.setValues(parameters)
  18542. }
  18543. copy(source) {
  18544. super.copy(source)
  18545. this.color.copy(source.color)
  18546. this.map = source.map
  18547. this.alphaMap = source.alphaMap
  18548. this.size = source.size
  18549. this.sizeAttenuation = source.sizeAttenuation
  18550. this.fog = source.fog
  18551. return this
  18552. }
  18553. }
  18554. const _inverseMatrix = /*@__PURE__*/ new Matrix4()
  18555. const _ray = /*@__PURE__*/ new Ray()
  18556. const _sphere = /*@__PURE__*/ new Sphere()
  18557. const _position$2 = /*@__PURE__*/ new Vector3()
  18558. class Points extends Object3D {
  18559. constructor(geometry = new BufferGeometry(), material = new PointsMaterial()) {
  18560. super()
  18561. this.isPoints = true
  18562. this.type = 'Points'
  18563. this.geometry = geometry
  18564. this.material = material
  18565. this.updateMorphTargets()
  18566. }
  18567. copy(source, recursive) {
  18568. super.copy(source, recursive)
  18569. this.material = source.material
  18570. this.geometry = source.geometry
  18571. return this
  18572. }
  18573. raycast(raycaster, intersects) {
  18574. const geometry = this.geometry
  18575. const matrixWorld = this.matrixWorld
  18576. const threshold = raycaster.params.Points.threshold
  18577. const drawRange = geometry.drawRange
  18578. // Checking boundingSphere distance to ray
  18579. if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
  18580. _sphere.copy(geometry.boundingSphere)
  18581. _sphere.applyMatrix4(matrixWorld)
  18582. _sphere.radius += threshold
  18583. if (raycaster.ray.intersectsSphere(_sphere) === false) return
  18584. //
  18585. _inverseMatrix.copy(matrixWorld).invert()
  18586. _ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix)
  18587. const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3)
  18588. const localThresholdSq = localThreshold * localThreshold
  18589. const index = geometry.index
  18590. const attributes = geometry.attributes
  18591. const positionAttribute = attributes.position
  18592. if (index !== null) {
  18593. const start = Math.max(0, drawRange.start)
  18594. const end = Math.min(index.count, drawRange.start + drawRange.count)
  18595. for (let i = start, il = end; i < il; i++) {
  18596. const a = index.getX(i)
  18597. _position$2.fromBufferAttribute(positionAttribute, a)
  18598. testPoint(_position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this)
  18599. }
  18600. } else {
  18601. const start = Math.max(0, drawRange.start)
  18602. const end = Math.min(positionAttribute.count, drawRange.start + drawRange.count)
  18603. for (let i = start, l = end; i < l; i++) {
  18604. _position$2.fromBufferAttribute(positionAttribute, i)
  18605. testPoint(_position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this)
  18606. }
  18607. }
  18608. }
  18609. updateMorphTargets() {
  18610. const geometry = this.geometry
  18611. const morphAttributes = geometry.morphAttributes
  18612. const keys = Object.keys(morphAttributes)
  18613. if (keys.length > 0) {
  18614. const morphAttribute = morphAttributes[keys[0]]
  18615. if (morphAttribute !== undefined) {
  18616. this.morphTargetInfluences = []
  18617. this.morphTargetDictionary = {}
  18618. for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
  18619. const name = morphAttribute[m].name || String(m)
  18620. this.morphTargetInfluences.push(0)
  18621. this.morphTargetDictionary[name] = m
  18622. }
  18623. }
  18624. }
  18625. }
  18626. }
  18627. function testPoint(point, index, localThresholdSq, matrixWorld, raycaster, intersects, object) {
  18628. const rayPointDistanceSq = _ray.distanceSqToPoint(point)
  18629. if (rayPointDistanceSq < localThresholdSq) {
  18630. const intersectPoint = new Vector3()
  18631. _ray.closestPointToPoint(point, intersectPoint)
  18632. intersectPoint.applyMatrix4(matrixWorld)
  18633. const distance = raycaster.ray.origin.distanceTo(intersectPoint)
  18634. if (distance < raycaster.near || distance > raycaster.far) return
  18635. intersects.push({
  18636. distance: distance,
  18637. distanceToRay: Math.sqrt(rayPointDistanceSq),
  18638. point: intersectPoint,
  18639. index: index,
  18640. face: null,
  18641. object: object
  18642. })
  18643. }
  18644. }
  18645. class VideoTexture extends Texture {
  18646. constructor(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
  18647. super(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy)
  18648. this.isVideoTexture = true
  18649. this.minFilter = minFilter !== undefined ? minFilter : LinearFilter
  18650. this.magFilter = magFilter !== undefined ? magFilter : LinearFilter
  18651. this.generateMipmaps = false
  18652. const scope = this
  18653. function updateVideo() {
  18654. scope.needsUpdate = true
  18655. video.requestVideoFrameCallback(updateVideo)
  18656. }
  18657. if ('requestVideoFrameCallback' in video) {
  18658. video.requestVideoFrameCallback(updateVideo)
  18659. }
  18660. }
  18661. clone() {
  18662. return new this.constructor(this.image).copy(this)
  18663. }
  18664. update() {
  18665. const video = this.image
  18666. const hasVideoFrameCallback = 'requestVideoFrameCallback' in video
  18667. if (hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA) {
  18668. this.needsUpdate = true
  18669. }
  18670. }
  18671. }
  18672. class FramebufferTexture extends Texture {
  18673. constructor(width, height, format) {
  18674. super({ width, height })
  18675. this.isFramebufferTexture = true
  18676. this.format = format
  18677. this.magFilter = NearestFilter
  18678. this.minFilter = NearestFilter
  18679. this.generateMipmaps = false
  18680. this.needsUpdate = true
  18681. }
  18682. }
  18683. class CompressedTexture extends Texture {
  18684. constructor(mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
  18685. super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding)
  18686. this.isCompressedTexture = true
  18687. this.image = { width: width, height: height }
  18688. this.mipmaps = mipmaps
  18689. // no flipping for cube textures
  18690. // (also flipping doesn't work for compressed textures )
  18691. this.flipY = false
  18692. // can't generate mipmaps for compressed textures
  18693. // mips must be embedded in DDS files
  18694. this.generateMipmaps = false
  18695. }
  18696. }
  18697. class CanvasTexture extends Texture {
  18698. constructor(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
  18699. super(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy)
  18700. this.isCanvasTexture = true
  18701. this.needsUpdate = true
  18702. }
  18703. }
  18704. /**
  18705. * Extensible curve object.
  18706. *
  18707. * Some common of curve methods:
  18708. * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
  18709. * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
  18710. * .getPoints(), .getSpacedPoints()
  18711. * .getLength()
  18712. * .updateArcLengths()
  18713. *
  18714. * This following curves inherit from THREE.Curve:
  18715. *
  18716. * -- 2D curves --
  18717. * THREE.ArcCurve
  18718. * THREE.CubicBezierCurve
  18719. * THREE.EllipseCurve
  18720. * THREE.LineCurve
  18721. * THREE.QuadraticBezierCurve
  18722. * THREE.SplineCurve
  18723. *
  18724. * -- 3D curves --
  18725. * THREE.CatmullRomCurve3
  18726. * THREE.CubicBezierCurve3
  18727. * THREE.LineCurve3
  18728. * THREE.QuadraticBezierCurve3
  18729. *
  18730. * A series of curves can be represented as a THREE.CurvePath.
  18731. *
  18732. **/
  18733. class Curve {
  18734. constructor() {
  18735. this.type = 'Curve'
  18736. this.arcLengthDivisions = 200
  18737. }
  18738. // Virtual base class method to overwrite and implement in subclasses
  18739. // - t [0 .. 1]
  18740. getPoint(/* t, optionalTarget */) {
  18741. console.warn('THREE.Curve: .getPoint() not implemented.')
  18742. return null
  18743. }
  18744. // Get point at relative position in curve according to arc length
  18745. // - u [0 .. 1]
  18746. getPointAt(u, optionalTarget) {
  18747. const t = this.getUtoTmapping(u)
  18748. return this.getPoint(t, optionalTarget)
  18749. }
  18750. // Get sequence of points using getPoint( t )
  18751. getPoints(divisions = 5) {
  18752. const points = []
  18753. for (let d = 0; d <= divisions; d++) {
  18754. points.push(this.getPoint(d / divisions))
  18755. }
  18756. return points
  18757. }
  18758. // Get sequence of points using getPointAt( u )
  18759. getSpacedPoints(divisions = 5) {
  18760. const points = []
  18761. for (let d = 0; d <= divisions; d++) {
  18762. points.push(this.getPointAt(d / divisions))
  18763. }
  18764. return points
  18765. }
  18766. // Get total curve arc length
  18767. getLength() {
  18768. const lengths = this.getLengths()
  18769. return lengths[lengths.length - 1]
  18770. }
  18771. // Get list of cumulative segment lengths
  18772. getLengths(divisions = this.arcLengthDivisions) {
  18773. if (this.cacheArcLengths && this.cacheArcLengths.length === divisions + 1 && !this.needsUpdate) {
  18774. return this.cacheArcLengths
  18775. }
  18776. this.needsUpdate = false
  18777. const cache = []
  18778. let current,
  18779. last = this.getPoint(0)
  18780. let sum = 0
  18781. cache.push(0)
  18782. for (let p = 1; p <= divisions; p++) {
  18783. current = this.getPoint(p / divisions)
  18784. sum += current.distanceTo(last)
  18785. cache.push(sum)
  18786. last = current
  18787. }
  18788. this.cacheArcLengths = cache
  18789. return cache // { sums: cache, sum: sum }; Sum is in the last element.
  18790. }
  18791. updateArcLengths() {
  18792. this.needsUpdate = true
  18793. this.getLengths()
  18794. }
  18795. // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
  18796. getUtoTmapping(u, distance) {
  18797. const arcLengths = this.getLengths()
  18798. let i = 0
  18799. const il = arcLengths.length
  18800. let targetArcLength // The targeted u distance value to get
  18801. if (distance) {
  18802. targetArcLength = distance
  18803. } else {
  18804. targetArcLength = u * arcLengths[il - 1]
  18805. }
  18806. // binary search for the index with largest value smaller than target u distance
  18807. let low = 0,
  18808. high = il - 1,
  18809. comparison
  18810. while (low <= high) {
  18811. i = Math.floor(low + (high - low) / 2) // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
  18812. comparison = arcLengths[i] - targetArcLength
  18813. if (comparison < 0) {
  18814. low = i + 1
  18815. } else if (comparison > 0) {
  18816. high = i - 1
  18817. } else {
  18818. high = i
  18819. break
  18820. // DONE
  18821. }
  18822. }
  18823. i = high
  18824. if (arcLengths[i] === targetArcLength) {
  18825. return i / (il - 1)
  18826. }
  18827. // we could get finer grain at lengths, or use simple interpolation between two points
  18828. const lengthBefore = arcLengths[i]
  18829. const lengthAfter = arcLengths[i + 1]
  18830. const segmentLength = lengthAfter - lengthBefore
  18831. // determine where we are between the 'before' and 'after' points
  18832. const segmentFraction = (targetArcLength - lengthBefore) / segmentLength
  18833. // add that fractional amount to t
  18834. const t = (i + segmentFraction) / (il - 1)
  18835. return t
  18836. }
  18837. // Returns a unit vector tangent at t
  18838. // In case any sub curve does not implement its tangent derivation,
  18839. // 2 points a small delta apart will be used to find its gradient
  18840. // which seems to give a reasonable approximation
  18841. getTangent(t, optionalTarget) {
  18842. const delta = 0.0001
  18843. let t1 = t - delta
  18844. let t2 = t + delta
  18845. // Capping in case of danger
  18846. if (t1 < 0) t1 = 0
  18847. if (t2 > 1) t2 = 1
  18848. const pt1 = this.getPoint(t1)
  18849. const pt2 = this.getPoint(t2)
  18850. const tangent = optionalTarget || (pt1.isVector2 ? new Vector2() : new Vector3())
  18851. tangent
  18852. .copy(pt2)
  18853. .sub(pt1)
  18854. .normalize()
  18855. return tangent
  18856. }
  18857. getTangentAt(u, optionalTarget) {
  18858. const t = this.getUtoTmapping(u)
  18859. return this.getTangent(t, optionalTarget)
  18860. }
  18861. computeFrenetFrames(segments, closed) {
  18862. // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
  18863. const normal = new Vector3()
  18864. const tangents = []
  18865. const normals = []
  18866. const binormals = []
  18867. const vec = new Vector3()
  18868. const mat = new Matrix4()
  18869. // compute the tangent vectors for each segment on the curve
  18870. for (let i = 0; i <= segments; i++) {
  18871. const u = i / segments
  18872. tangents[i] = this.getTangentAt(u, new Vector3())
  18873. }
  18874. // select an initial normal vector perpendicular to the first tangent vector,
  18875. // and in the direction of the minimum tangent xyz component
  18876. normals[0] = new Vector3()
  18877. binormals[0] = new Vector3()
  18878. let min = Number.MAX_VALUE
  18879. const tx = Math.abs(tangents[0].x)
  18880. const ty = Math.abs(tangents[0].y)
  18881. const tz = Math.abs(tangents[0].z)
  18882. if (tx <= min) {
  18883. min = tx
  18884. normal.set(1, 0, 0)
  18885. }
  18886. if (ty <= min) {
  18887. min = ty
  18888. normal.set(0, 1, 0)
  18889. }
  18890. if (tz <= min) {
  18891. normal.set(0, 0, 1)
  18892. }
  18893. vec.crossVectors(tangents[0], normal).normalize()
  18894. normals[0].crossVectors(tangents[0], vec)
  18895. binormals[0].crossVectors(tangents[0], normals[0])
  18896. // compute the slowly-varying normal and binormal vectors for each segment on the curve
  18897. for (let i = 1; i <= segments; i++) {
  18898. normals[i] = normals[i - 1].clone()
  18899. binormals[i] = binormals[i - 1].clone()
  18900. vec.crossVectors(tangents[i - 1], tangents[i])
  18901. if (vec.length() > Number.EPSILON) {
  18902. vec.normalize()
  18903. const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), -1, 1)) // clamp for floating pt errors
  18904. normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta))
  18905. }
  18906. binormals[i].crossVectors(tangents[i], normals[i])
  18907. }
  18908. // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
  18909. if (closed === true) {
  18910. let theta = Math.acos(clamp(normals[0].dot(normals[segments]), -1, 1))
  18911. theta /= segments
  18912. if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
  18913. theta = -theta
  18914. }
  18915. for (let i = 1; i <= segments; i++) {
  18916. // twist a little...
  18917. normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i))
  18918. binormals[i].crossVectors(tangents[i], normals[i])
  18919. }
  18920. }
  18921. return {
  18922. tangents: tangents,
  18923. normals: normals,
  18924. binormals: binormals
  18925. }
  18926. }
  18927. clone() {
  18928. return new this.constructor().copy(this)
  18929. }
  18930. copy(source) {
  18931. this.arcLengthDivisions = source.arcLengthDivisions
  18932. return this
  18933. }
  18934. toJSON() {
  18935. const data = {
  18936. metadata: {
  18937. version: 4.5,
  18938. type: 'Curve',
  18939. generator: 'Curve.toJSON'
  18940. }
  18941. }
  18942. data.arcLengthDivisions = this.arcLengthDivisions
  18943. data.type = this.type
  18944. return data
  18945. }
  18946. fromJSON(json) {
  18947. this.arcLengthDivisions = json.arcLengthDivisions
  18948. return this
  18949. }
  18950. }
  18951. class EllipseCurve extends Curve {
  18952. constructor(aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0) {
  18953. super()
  18954. this.isEllipseCurve = true
  18955. this.type = 'EllipseCurve'
  18956. this.aX = aX
  18957. this.aY = aY
  18958. this.xRadius = xRadius
  18959. this.yRadius = yRadius
  18960. this.aStartAngle = aStartAngle
  18961. this.aEndAngle = aEndAngle
  18962. this.aClockwise = aClockwise
  18963. this.aRotation = aRotation
  18964. }
  18965. getPoint(t, optionalTarget) {
  18966. const point = optionalTarget || new Vector2()
  18967. const twoPi = Math.PI * 2
  18968. let deltaAngle = this.aEndAngle - this.aStartAngle
  18969. const samePoints = Math.abs(deltaAngle) < Number.EPSILON
  18970. // ensures that deltaAngle is 0 .. 2 PI
  18971. while (deltaAngle < 0) deltaAngle += twoPi
  18972. while (deltaAngle > twoPi) deltaAngle -= twoPi
  18973. if (deltaAngle < Number.EPSILON) {
  18974. if (samePoints) {
  18975. deltaAngle = 0
  18976. } else {
  18977. deltaAngle = twoPi
  18978. }
  18979. }
  18980. if (this.aClockwise === true && !samePoints) {
  18981. if (deltaAngle === twoPi) {
  18982. deltaAngle = -twoPi
  18983. } else {
  18984. deltaAngle = deltaAngle - twoPi
  18985. }
  18986. }
  18987. const angle = this.aStartAngle + t * deltaAngle
  18988. let x = this.aX + this.xRadius * Math.cos(angle)
  18989. let y = this.aY + this.yRadius * Math.sin(angle)
  18990. if (this.aRotation !== 0) {
  18991. const cos = Math.cos(this.aRotation)
  18992. const sin = Math.sin(this.aRotation)
  18993. const tx = x - this.aX
  18994. const ty = y - this.aY
  18995. // Rotate the point about the center of the ellipse.
  18996. x = tx * cos - ty * sin + this.aX
  18997. y = tx * sin + ty * cos + this.aY
  18998. }
  18999. return point.set(x, y)
  19000. }
  19001. copy(source) {
  19002. super.copy(source)
  19003. this.aX = source.aX
  19004. this.aY = source.aY
  19005. this.xRadius = source.xRadius
  19006. this.yRadius = source.yRadius
  19007. this.aStartAngle = source.aStartAngle
  19008. this.aEndAngle = source.aEndAngle
  19009. this.aClockwise = source.aClockwise
  19010. this.aRotation = source.aRotation
  19011. return this
  19012. }
  19013. toJSON() {
  19014. const data = super.toJSON()
  19015. data.aX = this.aX
  19016. data.aY = this.aY
  19017. data.xRadius = this.xRadius
  19018. data.yRadius = this.yRadius
  19019. data.aStartAngle = this.aStartAngle
  19020. data.aEndAngle = this.aEndAngle
  19021. data.aClockwise = this.aClockwise
  19022. data.aRotation = this.aRotation
  19023. return data
  19024. }
  19025. fromJSON(json) {
  19026. super.fromJSON(json)
  19027. this.aX = json.aX
  19028. this.aY = json.aY
  19029. this.xRadius = json.xRadius
  19030. this.yRadius = json.yRadius
  19031. this.aStartAngle = json.aStartAngle
  19032. this.aEndAngle = json.aEndAngle
  19033. this.aClockwise = json.aClockwise
  19034. this.aRotation = json.aRotation
  19035. return this
  19036. }
  19037. }
  19038. class ArcCurve extends EllipseCurve {
  19039. constructor(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
  19040. super(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise)
  19041. this.isArcCurve = true
  19042. this.type = 'ArcCurve'
  19043. }
  19044. }
  19045. /**
  19046. * Centripetal CatmullRom Curve - which is useful for avoiding
  19047. * cusps and self-intersections in non-uniform catmull rom curves.
  19048. * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
  19049. *
  19050. * curve.type accepts centripetal(default), chordal and catmullrom
  19051. * curve.tension is used for catmullrom which defaults to 0.5
  19052. */
  19053. /*
  19054. Based on an optimized c++ solution in
  19055. - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
  19056. - http://ideone.com/NoEbVM
  19057. This CubicPoly class could be used for reusing some variables and calculations,
  19058. but for three.js curve use, it could be possible inlined and flatten into a single function call
  19059. which can be placed in CurveUtils.
  19060. */
  19061. function CubicPoly() {
  19062. let c0 = 0,
  19063. c1 = 0,
  19064. c2 = 0,
  19065. c3 = 0
  19066. /*
  19067. * Compute coefficients for a cubic polynomial
  19068. * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
  19069. * such that
  19070. * p(0) = x0, p(1) = x1
  19071. * and
  19072. * p'(0) = t0, p'(1) = t1.
  19073. */
  19074. function init(x0, x1, t0, t1) {
  19075. c0 = x0
  19076. c1 = t0
  19077. c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1
  19078. c3 = 2 * x0 - 2 * x1 + t0 + t1
  19079. }
  19080. return {
  19081. initCatmullRom: function(x0, x1, x2, x3, tension) {
  19082. init(x1, x2, tension * (x2 - x0), tension * (x3 - x1))
  19083. },
  19084. initNonuniformCatmullRom: function(x0, x1, x2, x3, dt0, dt1, dt2) {
  19085. // compute tangents when parameterized in [t1,t2]
  19086. let t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1
  19087. let t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2
  19088. // rescale tangents for parametrization in [0,1]
  19089. t1 *= dt1
  19090. t2 *= dt1
  19091. init(x1, x2, t1, t2)
  19092. },
  19093. calc: function(t) {
  19094. const t2 = t * t
  19095. const t3 = t2 * t
  19096. return c0 + c1 * t + c2 * t2 + c3 * t3
  19097. }
  19098. }
  19099. }
  19100. //
  19101. const tmp = new Vector3()
  19102. const px = new CubicPoly(),
  19103. py = new CubicPoly(),
  19104. pz = new CubicPoly()
  19105. class CatmullRomCurve3 extends Curve {
  19106. constructor(points = [], closed = false, curveType = 'centripetal', tension = 0.5) {
  19107. super()
  19108. this.isCatmullRomCurve3 = true
  19109. this.type = 'CatmullRomCurve3'
  19110. this.points = points
  19111. this.closed = closed
  19112. this.curveType = curveType
  19113. this.tension = tension
  19114. }
  19115. getPoint(t, optionalTarget = new Vector3()) {
  19116. const point = optionalTarget
  19117. const points = this.points
  19118. const l = points.length
  19119. const p = (l - (this.closed ? 0 : 1)) * t
  19120. let intPoint = Math.floor(p)
  19121. let weight = p - intPoint
  19122. if (this.closed) {
  19123. intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / l) + 1) * l
  19124. } else if (weight === 0 && intPoint === l - 1) {
  19125. intPoint = l - 2
  19126. weight = 1
  19127. }
  19128. let p0, p3 // 4 points (p1 & p2 defined below)
  19129. if (this.closed || intPoint > 0) {
  19130. p0 = points[(intPoint - 1) % l]
  19131. } else {
  19132. // extrapolate first point
  19133. tmp.subVectors(points[0], points[1]).add(points[0])
  19134. p0 = tmp
  19135. }
  19136. const p1 = points[intPoint % l]
  19137. const p2 = points[(intPoint + 1) % l]
  19138. if (this.closed || intPoint + 2 < l) {
  19139. p3 = points[(intPoint + 2) % l]
  19140. } else {
  19141. // extrapolate last point
  19142. tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1])
  19143. p3 = tmp
  19144. }
  19145. if (this.curveType === 'centripetal' || this.curveType === 'chordal') {
  19146. // init Centripetal / Chordal Catmull-Rom
  19147. const pow = this.curveType === 'chordal' ? 0.5 : 0.25
  19148. let dt0 = Math.pow(p0.distanceToSquared(p1), pow)
  19149. let dt1 = Math.pow(p1.distanceToSquared(p2), pow)
  19150. let dt2 = Math.pow(p2.distanceToSquared(p3), pow)
  19151. // safety check for repeated points
  19152. if (dt1 < 1e-4) dt1 = 1.0
  19153. if (dt0 < 1e-4) dt0 = dt1
  19154. if (dt2 < 1e-4) dt2 = dt1
  19155. px.initNonuniformCatmullRom(p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2)
  19156. py.initNonuniformCatmullRom(p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2)
  19157. pz.initNonuniformCatmullRom(p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2)
  19158. } else if (this.curveType === 'catmullrom') {
  19159. px.initCatmullRom(p0.x, p1.x, p2.x, p3.x, this.tension)
  19160. py.initCatmullRom(p0.y, p1.y, p2.y, p3.y, this.tension)
  19161. pz.initCatmullRom(p0.z, p1.z, p2.z, p3.z, this.tension)
  19162. }
  19163. point.set(px.calc(weight), py.calc(weight), pz.calc(weight))
  19164. return point
  19165. }
  19166. copy(source) {
  19167. super.copy(source)
  19168. this.points = []
  19169. for (let i = 0, l = source.points.length; i < l; i++) {
  19170. const point = source.points[i]
  19171. this.points.push(point.clone())
  19172. }
  19173. this.closed = source.closed
  19174. this.curveType = source.curveType
  19175. this.tension = source.tension
  19176. return this
  19177. }
  19178. toJSON() {
  19179. const data = super.toJSON()
  19180. data.points = []
  19181. for (let i = 0, l = this.points.length; i < l; i++) {
  19182. const point = this.points[i]
  19183. data.points.push(point.toArray())
  19184. }
  19185. data.closed = this.closed
  19186. data.curveType = this.curveType
  19187. data.tension = this.tension
  19188. return data
  19189. }
  19190. fromJSON(json) {
  19191. super.fromJSON(json)
  19192. this.points = []
  19193. for (let i = 0, l = json.points.length; i < l; i++) {
  19194. const point = json.points[i]
  19195. this.points.push(new Vector3().fromArray(point))
  19196. }
  19197. this.closed = json.closed
  19198. this.curveType = json.curveType
  19199. this.tension = json.tension
  19200. return this
  19201. }
  19202. }
  19203. /**
  19204. * Bezier Curves formulas obtained from
  19205. * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
  19206. */
  19207. function CatmullRom(t, p0, p1, p2, p3) {
  19208. const v0 = (p2 - p0) * 0.5
  19209. const v1 = (p3 - p1) * 0.5
  19210. const t2 = t * t
  19211. const t3 = t * t2
  19212. return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1
  19213. }
  19214. //
  19215. function QuadraticBezierP0(t, p) {
  19216. const k = 1 - t
  19217. return k * k * p
  19218. }
  19219. function QuadraticBezierP1(t, p) {
  19220. return 2 * (1 - t) * t * p
  19221. }
  19222. function QuadraticBezierP2(t, p) {
  19223. return t * t * p
  19224. }
  19225. function QuadraticBezier(t, p0, p1, p2) {
  19226. return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) + QuadraticBezierP2(t, p2)
  19227. }
  19228. //
  19229. function CubicBezierP0(t, p) {
  19230. const k = 1 - t
  19231. return k * k * k * p
  19232. }
  19233. function CubicBezierP1(t, p) {
  19234. const k = 1 - t
  19235. return 3 * k * k * t * p
  19236. }
  19237. function CubicBezierP2(t, p) {
  19238. return 3 * (1 - t) * t * t * p
  19239. }
  19240. function CubicBezierP3(t, p) {
  19241. return t * t * t * p
  19242. }
  19243. function CubicBezier(t, p0, p1, p2, p3) {
  19244. return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) + CubicBezierP3(t, p3)
  19245. }
  19246. class CubicBezierCurve extends Curve {
  19247. constructor(v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2()) {
  19248. super()
  19249. this.isCubicBezierCurve = true
  19250. this.type = 'CubicBezierCurve'
  19251. this.v0 = v0
  19252. this.v1 = v1
  19253. this.v2 = v2
  19254. this.v3 = v3
  19255. }
  19256. getPoint(t, optionalTarget = new Vector2()) {
  19257. const point = optionalTarget
  19258. const v0 = this.v0,
  19259. v1 = this.v1,
  19260. v2 = this.v2,
  19261. v3 = this.v3
  19262. point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y))
  19263. return point
  19264. }
  19265. copy(source) {
  19266. super.copy(source)
  19267. this.v0.copy(source.v0)
  19268. this.v1.copy(source.v1)
  19269. this.v2.copy(source.v2)
  19270. this.v3.copy(source.v3)
  19271. return this
  19272. }
  19273. toJSON() {
  19274. const data = super.toJSON()
  19275. data.v0 = this.v0.toArray()
  19276. data.v1 = this.v1.toArray()
  19277. data.v2 = this.v2.toArray()
  19278. data.v3 = this.v3.toArray()
  19279. return data
  19280. }
  19281. fromJSON(json) {
  19282. super.fromJSON(json)
  19283. this.v0.fromArray(json.v0)
  19284. this.v1.fromArray(json.v1)
  19285. this.v2.fromArray(json.v2)
  19286. this.v3.fromArray(json.v3)
  19287. return this
  19288. }
  19289. }
  19290. class CubicBezierCurve3 extends Curve {
  19291. constructor(v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3()) {
  19292. super()
  19293. this.isCubicBezierCurve3 = true
  19294. this.type = 'CubicBezierCurve3'
  19295. this.v0 = v0
  19296. this.v1 = v1
  19297. this.v2 = v2
  19298. this.v3 = v3
  19299. }
  19300. getPoint(t, optionalTarget = new Vector3()) {
  19301. const point = optionalTarget
  19302. const v0 = this.v0,
  19303. v1 = this.v1,
  19304. v2 = this.v2,
  19305. v3 = this.v3
  19306. point.set(CubicBezier(t, v0.x, v1.x, v2.x, v3.x), CubicBezier(t, v0.y, v1.y, v2.y, v3.y), CubicBezier(t, v0.z, v1.z, v2.z, v3.z))
  19307. return point
  19308. }
  19309. copy(source) {
  19310. super.copy(source)
  19311. this.v0.copy(source.v0)
  19312. this.v1.copy(source.v1)
  19313. this.v2.copy(source.v2)
  19314. this.v3.copy(source.v3)
  19315. return this
  19316. }
  19317. toJSON() {
  19318. const data = super.toJSON()
  19319. data.v0 = this.v0.toArray()
  19320. data.v1 = this.v1.toArray()
  19321. data.v2 = this.v2.toArray()
  19322. data.v3 = this.v3.toArray()
  19323. return data
  19324. }
  19325. fromJSON(json) {
  19326. super.fromJSON(json)
  19327. this.v0.fromArray(json.v0)
  19328. this.v1.fromArray(json.v1)
  19329. this.v2.fromArray(json.v2)
  19330. this.v3.fromArray(json.v3)
  19331. return this
  19332. }
  19333. }
  19334. class LineCurve extends Curve {
  19335. constructor(v1 = new Vector2(), v2 = new Vector2()) {
  19336. super()
  19337. this.isLineCurve = true
  19338. this.type = 'LineCurve'
  19339. this.v1 = v1
  19340. this.v2 = v2
  19341. }
  19342. getPoint(t, optionalTarget = new Vector2()) {
  19343. const point = optionalTarget
  19344. if (t === 1) {
  19345. point.copy(this.v2)
  19346. } else {
  19347. point.copy(this.v2).sub(this.v1)
  19348. point.multiplyScalar(t).add(this.v1)
  19349. }
  19350. return point
  19351. }
  19352. // Line curve is linear, so we can overwrite default getPointAt
  19353. getPointAt(u, optionalTarget) {
  19354. return this.getPoint(u, optionalTarget)
  19355. }
  19356. getTangent(t, optionalTarget) {
  19357. const tangent = optionalTarget || new Vector2()
  19358. tangent
  19359. .copy(this.v2)
  19360. .sub(this.v1)
  19361. .normalize()
  19362. return tangent
  19363. }
  19364. copy(source) {
  19365. super.copy(source)
  19366. this.v1.copy(source.v1)
  19367. this.v2.copy(source.v2)
  19368. return this
  19369. }
  19370. toJSON() {
  19371. const data = super.toJSON()
  19372. data.v1 = this.v1.toArray()
  19373. data.v2 = this.v2.toArray()
  19374. return data
  19375. }
  19376. fromJSON(json) {
  19377. super.fromJSON(json)
  19378. this.v1.fromArray(json.v1)
  19379. this.v2.fromArray(json.v2)
  19380. return this
  19381. }
  19382. }
  19383. class LineCurve3 extends Curve {
  19384. constructor(v1 = new Vector3(), v2 = new Vector3()) {
  19385. super()
  19386. this.isLineCurve3 = true
  19387. this.type = 'LineCurve3'
  19388. this.v1 = v1
  19389. this.v2 = v2
  19390. }
  19391. getPoint(t, optionalTarget = new Vector3()) {
  19392. const point = optionalTarget
  19393. if (t === 1) {
  19394. point.copy(this.v2)
  19395. } else {
  19396. point.copy(this.v2).sub(this.v1)
  19397. point.multiplyScalar(t).add(this.v1)
  19398. }
  19399. return point
  19400. }
  19401. // Line curve is linear, so we can overwrite default getPointAt
  19402. getPointAt(u, optionalTarget) {
  19403. return this.getPoint(u, optionalTarget)
  19404. }
  19405. copy(source) {
  19406. super.copy(source)
  19407. this.v1.copy(source.v1)
  19408. this.v2.copy(source.v2)
  19409. return this
  19410. }
  19411. toJSON() {
  19412. const data = super.toJSON()
  19413. data.v1 = this.v1.toArray()
  19414. data.v2 = this.v2.toArray()
  19415. return data
  19416. }
  19417. fromJSON(json) {
  19418. super.fromJSON(json)
  19419. this.v1.fromArray(json.v1)
  19420. this.v2.fromArray(json.v2)
  19421. return this
  19422. }
  19423. }
  19424. class QuadraticBezierCurve extends Curve {
  19425. constructor(v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2()) {
  19426. super()
  19427. this.isQuadraticBezierCurve = true
  19428. this.type = 'QuadraticBezierCurve'
  19429. this.v0 = v0
  19430. this.v1 = v1
  19431. this.v2 = v2
  19432. }
  19433. getPoint(t, optionalTarget = new Vector2()) {
  19434. const point = optionalTarget
  19435. const v0 = this.v0,
  19436. v1 = this.v1,
  19437. v2 = this.v2
  19438. point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y))
  19439. return point
  19440. }
  19441. copy(source) {
  19442. super.copy(source)
  19443. this.v0.copy(source.v0)
  19444. this.v1.copy(source.v1)
  19445. this.v2.copy(source.v2)
  19446. return this
  19447. }
  19448. toJSON() {
  19449. const data = super.toJSON()
  19450. data.v0 = this.v0.toArray()
  19451. data.v1 = this.v1.toArray()
  19452. data.v2 = this.v2.toArray()
  19453. return data
  19454. }
  19455. fromJSON(json) {
  19456. super.fromJSON(json)
  19457. this.v0.fromArray(json.v0)
  19458. this.v1.fromArray(json.v1)
  19459. this.v2.fromArray(json.v2)
  19460. return this
  19461. }
  19462. }
  19463. class QuadraticBezierCurve3 extends Curve {
  19464. constructor(v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3()) {
  19465. super()
  19466. this.isQuadraticBezierCurve3 = true
  19467. this.type = 'QuadraticBezierCurve3'
  19468. this.v0 = v0
  19469. this.v1 = v1
  19470. this.v2 = v2
  19471. }
  19472. getPoint(t, optionalTarget = new Vector3()) {
  19473. const point = optionalTarget
  19474. const v0 = this.v0,
  19475. v1 = this.v1,
  19476. v2 = this.v2
  19477. point.set(QuadraticBezier(t, v0.x, v1.x, v2.x), QuadraticBezier(t, v0.y, v1.y, v2.y), QuadraticBezier(t, v0.z, v1.z, v2.z))
  19478. return point
  19479. }
  19480. copy(source) {
  19481. super.copy(source)
  19482. this.v0.copy(source.v0)
  19483. this.v1.copy(source.v1)
  19484. this.v2.copy(source.v2)
  19485. return this
  19486. }
  19487. toJSON() {
  19488. const data = super.toJSON()
  19489. data.v0 = this.v0.toArray()
  19490. data.v1 = this.v1.toArray()
  19491. data.v2 = this.v2.toArray()
  19492. return data
  19493. }
  19494. fromJSON(json) {
  19495. super.fromJSON(json)
  19496. this.v0.fromArray(json.v0)
  19497. this.v1.fromArray(json.v1)
  19498. this.v2.fromArray(json.v2)
  19499. return this
  19500. }
  19501. }
  19502. class SplineCurve extends Curve {
  19503. constructor(points = []) {
  19504. super()
  19505. this.isSplineCurve = true
  19506. this.type = 'SplineCurve'
  19507. this.points = points
  19508. }
  19509. getPoint(t, optionalTarget = new Vector2()) {
  19510. const point = optionalTarget
  19511. const points = this.points
  19512. const p = (points.length - 1) * t
  19513. const intPoint = Math.floor(p)
  19514. const weight = p - intPoint
  19515. const p0 = points[intPoint === 0 ? intPoint : intPoint - 1]
  19516. const p1 = points[intPoint]
  19517. const p2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1]
  19518. const p3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2]
  19519. point.set(CatmullRom(weight, p0.x, p1.x, p2.x, p3.x), CatmullRom(weight, p0.y, p1.y, p2.y, p3.y))
  19520. return point
  19521. }
  19522. copy(source) {
  19523. super.copy(source)
  19524. this.points = []
  19525. for (let i = 0, l = source.points.length; i < l; i++) {
  19526. const point = source.points[i]
  19527. this.points.push(point.clone())
  19528. }
  19529. return this
  19530. }
  19531. toJSON() {
  19532. const data = super.toJSON()
  19533. data.points = []
  19534. for (let i = 0, l = this.points.length; i < l; i++) {
  19535. const point = this.points[i]
  19536. data.points.push(point.toArray())
  19537. }
  19538. return data
  19539. }
  19540. fromJSON(json) {
  19541. super.fromJSON(json)
  19542. this.points = []
  19543. for (let i = 0, l = json.points.length; i < l; i++) {
  19544. const point = json.points[i]
  19545. this.points.push(new Vector2().fromArray(point))
  19546. }
  19547. return this
  19548. }
  19549. }
  19550. var Curves = /*#__PURE__*/ Object.freeze({
  19551. __proto__: null,
  19552. ArcCurve: ArcCurve,
  19553. CatmullRomCurve3: CatmullRomCurve3,
  19554. CubicBezierCurve: CubicBezierCurve,
  19555. CubicBezierCurve3: CubicBezierCurve3,
  19556. EllipseCurve: EllipseCurve,
  19557. LineCurve: LineCurve,
  19558. LineCurve3: LineCurve3,
  19559. QuadraticBezierCurve: QuadraticBezierCurve,
  19560. QuadraticBezierCurve3: QuadraticBezierCurve3,
  19561. SplineCurve: SplineCurve
  19562. })
  19563. /**************************************************************
  19564. * Curved Path - a curve path is simply a array of connected
  19565. * curves, but retains the api of a curve
  19566. **************************************************************/
  19567. class CurvePath extends Curve {
  19568. constructor() {
  19569. super()
  19570. this.type = 'CurvePath'
  19571. this.curves = []
  19572. this.autoClose = false // Automatically closes the path
  19573. }
  19574. add(curve) {
  19575. this.curves.push(curve)
  19576. }
  19577. closePath() {
  19578. // Add a line curve if start and end of lines are not connected
  19579. const startPoint = this.curves[0].getPoint(0)
  19580. const endPoint = this.curves[this.curves.length - 1].getPoint(1)
  19581. if (!startPoint.equals(endPoint)) {
  19582. this.curves.push(new LineCurve(endPoint, startPoint))
  19583. }
  19584. }
  19585. // To get accurate point with reference to
  19586. // entire path distance at time t,
  19587. // following has to be done:
  19588. // 1. Length of each sub path have to be known
  19589. // 2. Locate and identify type of curve
  19590. // 3. Get t for the curve
  19591. // 4. Return curve.getPointAt(t')
  19592. getPoint(t, optionalTarget) {
  19593. const d = t * this.getLength()
  19594. const curveLengths = this.getCurveLengths()
  19595. let i = 0
  19596. // To think about boundaries points.
  19597. while (i < curveLengths.length) {
  19598. if (curveLengths[i] >= d) {
  19599. const diff = curveLengths[i] - d
  19600. const curve = this.curves[i]
  19601. const segmentLength = curve.getLength()
  19602. const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength
  19603. return curve.getPointAt(u, optionalTarget)
  19604. }
  19605. i++
  19606. }
  19607. return null
  19608. // loop where sum != 0, sum > d , sum+1 <d
  19609. }
  19610. // We cannot use the default THREE.Curve getPoint() with getLength() because in
  19611. // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
  19612. // getPoint() depends on getLength
  19613. getLength() {
  19614. const lens = this.getCurveLengths()
  19615. return lens[lens.length - 1]
  19616. }
  19617. // cacheLengths must be recalculated.
  19618. updateArcLengths() {
  19619. this.needsUpdate = true
  19620. this.cacheLengths = null
  19621. this.getCurveLengths()
  19622. }
  19623. // Compute lengths and cache them
  19624. // We cannot overwrite getLengths() because UtoT mapping uses it.
  19625. getCurveLengths() {
  19626. // We use cache values if curves and cache array are same length
  19627. if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
  19628. return this.cacheLengths
  19629. }
  19630. // Get length of sub-curve
  19631. // Push sums into cached array
  19632. const lengths = []
  19633. let sums = 0
  19634. for (let i = 0, l = this.curves.length; i < l; i++) {
  19635. sums += this.curves[i].getLength()
  19636. lengths.push(sums)
  19637. }
  19638. this.cacheLengths = lengths
  19639. return lengths
  19640. }
  19641. getSpacedPoints(divisions = 40) {
  19642. const points = []
  19643. for (let i = 0; i <= divisions; i++) {
  19644. points.push(this.getPoint(i / divisions))
  19645. }
  19646. if (this.autoClose) {
  19647. points.push(points[0])
  19648. }
  19649. return points
  19650. }
  19651. getPoints(divisions = 12) {
  19652. const points = []
  19653. let last
  19654. for (let i = 0, curves = this.curves; i < curves.length; i++) {
  19655. const curve = curves[i]
  19656. const resolution = curve.isEllipseCurve ? divisions * 2 : curve.isLineCurve || curve.isLineCurve3 ? 1 : curve.isSplineCurve ? divisions * curve.points.length : divisions
  19657. const pts = curve.getPoints(resolution)
  19658. for (let j = 0; j < pts.length; j++) {
  19659. const point = pts[j]
  19660. if (last && last.equals(point)) continue // ensures no consecutive points are duplicates
  19661. points.push(point)
  19662. last = point
  19663. }
  19664. }
  19665. if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) {
  19666. points.push(points[0])
  19667. }
  19668. return points
  19669. }
  19670. copy(source) {
  19671. super.copy(source)
  19672. this.curves = []
  19673. for (let i = 0, l = source.curves.length; i < l; i++) {
  19674. const curve = source.curves[i]
  19675. this.curves.push(curve.clone())
  19676. }
  19677. this.autoClose = source.autoClose
  19678. return this
  19679. }
  19680. toJSON() {
  19681. const data = super.toJSON()
  19682. data.autoClose = this.autoClose
  19683. data.curves = []
  19684. for (let i = 0, l = this.curves.length; i < l; i++) {
  19685. const curve = this.curves[i]
  19686. data.curves.push(curve.toJSON())
  19687. }
  19688. return data
  19689. }
  19690. fromJSON(json) {
  19691. super.fromJSON(json)
  19692. this.autoClose = json.autoClose
  19693. this.curves = []
  19694. for (let i = 0, l = json.curves.length; i < l; i++) {
  19695. const curve = json.curves[i]
  19696. this.curves.push(new Curves[curve.type]().fromJSON(curve))
  19697. }
  19698. return this
  19699. }
  19700. }
  19701. class Path extends CurvePath {
  19702. constructor(points) {
  19703. super()
  19704. this.type = 'Path'
  19705. this.currentPoint = new Vector2()
  19706. if (points) {
  19707. this.setFromPoints(points)
  19708. }
  19709. }
  19710. setFromPoints(points) {
  19711. this.moveTo(points[0].x, points[0].y)
  19712. for (let i = 1, l = points.length; i < l; i++) {
  19713. this.lineTo(points[i].x, points[i].y)
  19714. }
  19715. return this
  19716. }
  19717. moveTo(x, y) {
  19718. this.currentPoint.set(x, y) // TODO consider referencing vectors instead of copying?
  19719. return this
  19720. }
  19721. lineTo(x, y) {
  19722. const curve = new LineCurve(this.currentPoint.clone(), new Vector2(x, y))
  19723. this.curves.push(curve)
  19724. this.currentPoint.set(x, y)
  19725. return this
  19726. }
  19727. quadraticCurveTo(aCPx, aCPy, aX, aY) {
  19728. const curve = new QuadraticBezierCurve(this.currentPoint.clone(), new Vector2(aCPx, aCPy), new Vector2(aX, aY))
  19729. this.curves.push(curve)
  19730. this.currentPoint.set(aX, aY)
  19731. return this
  19732. }
  19733. bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
  19734. const curve = new CubicBezierCurve(this.currentPoint.clone(), new Vector2(aCP1x, aCP1y), new Vector2(aCP2x, aCP2y), new Vector2(aX, aY))
  19735. this.curves.push(curve)
  19736. this.currentPoint.set(aX, aY)
  19737. return this
  19738. }
  19739. splineThru(pts /*Array of Vector*/) {
  19740. const npts = [this.currentPoint.clone()].concat(pts)
  19741. const curve = new SplineCurve(npts)
  19742. this.curves.push(curve)
  19743. this.currentPoint.copy(pts[pts.length - 1])
  19744. return this
  19745. }
  19746. arc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
  19747. const x0 = this.currentPoint.x
  19748. const y0 = this.currentPoint.y
  19749. this.absarc(aX + x0, aY + y0, aRadius, aStartAngle, aEndAngle, aClockwise)
  19750. return this
  19751. }
  19752. absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
  19753. this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise)
  19754. return this
  19755. }
  19756. ellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
  19757. const x0 = this.currentPoint.x
  19758. const y0 = this.currentPoint.y
  19759. this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation)
  19760. return this
  19761. }
  19762. absellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
  19763. const curve = new EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation)
  19764. if (this.curves.length > 0) {
  19765. // if a previous curve is present, attempt to join
  19766. const firstPoint = curve.getPoint(0)
  19767. if (!firstPoint.equals(this.currentPoint)) {
  19768. this.lineTo(firstPoint.x, firstPoint.y)
  19769. }
  19770. }
  19771. this.curves.push(curve)
  19772. const lastPoint = curve.getPoint(1)
  19773. this.currentPoint.copy(lastPoint)
  19774. return this
  19775. }
  19776. copy(source) {
  19777. super.copy(source)
  19778. this.currentPoint.copy(source.currentPoint)
  19779. return this
  19780. }
  19781. toJSON() {
  19782. const data = super.toJSON()
  19783. data.currentPoint = this.currentPoint.toArray()
  19784. return data
  19785. }
  19786. fromJSON(json) {
  19787. super.fromJSON(json)
  19788. this.currentPoint.fromArray(json.currentPoint)
  19789. return this
  19790. }
  19791. }
  19792. class LatheGeometry extends BufferGeometry {
  19793. constructor(points = [new Vector2(0, 0.5), new Vector2(0.5, 0), new Vector2(0, -0.5)], segments = 12, phiStart = 0, phiLength = Math.PI * 2) {
  19794. super()
  19795. this.type = 'LatheGeometry'
  19796. this.parameters = {
  19797. points: points,
  19798. segments: segments,
  19799. phiStart: phiStart,
  19800. phiLength: phiLength
  19801. }
  19802. segments = Math.floor(segments)
  19803. // clamp phiLength so it's in range of [ 0, 2PI ]
  19804. phiLength = clamp(phiLength, 0, Math.PI * 2)
  19805. // buffers
  19806. const indices = []
  19807. const vertices = []
  19808. const uvs = []
  19809. const initNormals = []
  19810. const normals = []
  19811. // helper variables
  19812. const inverseSegments = 1.0 / segments
  19813. const vertex = new Vector3()
  19814. const uv = new Vector2()
  19815. const normal = new Vector3()
  19816. const curNormal = new Vector3()
  19817. const prevNormal = new Vector3()
  19818. let dx = 0
  19819. let dy = 0
  19820. // pre-compute normals for initial "meridian"
  19821. for (let j = 0; j <= points.length - 1; j++) {
  19822. switch (j) {
  19823. case 0: // special handling for 1st vertex on path
  19824. dx = points[j + 1].x - points[j].x
  19825. dy = points[j + 1].y - points[j].y
  19826. normal.x = dy * 1.0
  19827. normal.y = -dx
  19828. normal.z = dy * 0.0
  19829. prevNormal.copy(normal)
  19830. normal.normalize()
  19831. initNormals.push(normal.x, normal.y, normal.z)
  19832. break
  19833. case points.length - 1: // special handling for last Vertex on path
  19834. initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z)
  19835. break
  19836. default:
  19837. // default handling for all vertices in between
  19838. dx = points[j + 1].x - points[j].x
  19839. dy = points[j + 1].y - points[j].y
  19840. normal.x = dy * 1.0
  19841. normal.y = -dx
  19842. normal.z = dy * 0.0
  19843. curNormal.copy(normal)
  19844. normal.x += prevNormal.x
  19845. normal.y += prevNormal.y
  19846. normal.z += prevNormal.z
  19847. normal.normalize()
  19848. initNormals.push(normal.x, normal.y, normal.z)
  19849. prevNormal.copy(curNormal)
  19850. }
  19851. }
  19852. // generate vertices, uvs and normals
  19853. for (let i = 0; i <= segments; i++) {
  19854. const phi = phiStart + i * inverseSegments * phiLength
  19855. const sin = Math.sin(phi)
  19856. const cos = Math.cos(phi)
  19857. for (let j = 0; j <= points.length - 1; j++) {
  19858. // vertex
  19859. vertex.x = points[j].x * sin
  19860. vertex.y = points[j].y
  19861. vertex.z = points[j].x * cos
  19862. vertices.push(vertex.x, vertex.y, vertex.z)
  19863. // uv
  19864. uv.x = i / segments
  19865. uv.y = j / (points.length - 1)
  19866. uvs.push(uv.x, uv.y)
  19867. // normal
  19868. const x = initNormals[3 * j + 0] * sin
  19869. const y = initNormals[3 * j + 1]
  19870. const z = initNormals[3 * j + 0] * cos
  19871. normals.push(x, y, z)
  19872. }
  19873. }
  19874. // indices
  19875. for (let i = 0; i < segments; i++) {
  19876. for (let j = 0; j < points.length - 1; j++) {
  19877. const base = j + i * points.length
  19878. const a = base
  19879. const b = base + points.length
  19880. const c = base + points.length + 1
  19881. const d = base + 1
  19882. // faces
  19883. indices.push(a, b, d)
  19884. indices.push(c, d, b)
  19885. }
  19886. }
  19887. // build geometry
  19888. this.setIndex(indices)
  19889. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  19890. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  19891. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  19892. }
  19893. static fromJSON(data) {
  19894. return new LatheGeometry(data.points, data.segments, data.phiStart, data.phiLength)
  19895. }
  19896. }
  19897. class CapsuleGeometry extends LatheGeometry {
  19898. constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
  19899. const path = new Path()
  19900. path.absarc(0, -length / 2, radius, Math.PI * 1.5, 0)
  19901. path.absarc(0, length / 2, radius, 0, Math.PI * 0.5)
  19902. super(path.getPoints(capSegments), radialSegments)
  19903. this.type = 'CapsuleGeometry'
  19904. this.parameters = {
  19905. radius: radius,
  19906. height: length,
  19907. capSegments: capSegments,
  19908. radialSegments: radialSegments
  19909. }
  19910. }
  19911. static fromJSON(data) {
  19912. return new CapsuleGeometry(data.radius, data.length, data.capSegments, data.radialSegments)
  19913. }
  19914. }
  19915. class CircleGeometry extends BufferGeometry {
  19916. constructor(radius = 1, segments = 8, thetaStart = 0, thetaLength = Math.PI * 2) {
  19917. super()
  19918. this.type = 'CircleGeometry'
  19919. this.parameters = {
  19920. radius: radius,
  19921. segments: segments,
  19922. thetaStart: thetaStart,
  19923. thetaLength: thetaLength
  19924. }
  19925. segments = Math.max(3, segments)
  19926. // buffers
  19927. const indices = []
  19928. const vertices = []
  19929. const normals = []
  19930. const uvs = []
  19931. // helper variables
  19932. const vertex = new Vector3()
  19933. const uv = new Vector2()
  19934. // center point
  19935. vertices.push(0, 0, 0)
  19936. normals.push(0, 0, 1)
  19937. uvs.push(0.5, 0.5)
  19938. for (let s = 0, i = 3; s <= segments; s++, i += 3) {
  19939. const segment = thetaStart + (s / segments) * thetaLength
  19940. // vertex
  19941. vertex.x = radius * Math.cos(segment)
  19942. vertex.y = radius * Math.sin(segment)
  19943. vertices.push(vertex.x, vertex.y, vertex.z)
  19944. // normal
  19945. normals.push(0, 0, 1)
  19946. // uvs
  19947. uv.x = (vertices[i] / radius + 1) / 2
  19948. uv.y = (vertices[i + 1] / radius + 1) / 2
  19949. uvs.push(uv.x, uv.y)
  19950. }
  19951. // indices
  19952. for (let i = 1; i <= segments; i++) {
  19953. indices.push(i, i + 1, 0)
  19954. }
  19955. // build geometry
  19956. this.setIndex(indices)
  19957. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  19958. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  19959. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  19960. }
  19961. static fromJSON(data) {
  19962. return new CircleGeometry(data.radius, data.segments, data.thetaStart, data.thetaLength)
  19963. }
  19964. }
  19965. class CylinderGeometry extends BufferGeometry {
  19966. constructor(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
  19967. super()
  19968. this.type = 'CylinderGeometry'
  19969. this.parameters = {
  19970. radiusTop: radiusTop,
  19971. radiusBottom: radiusBottom,
  19972. height: height,
  19973. radialSegments: radialSegments,
  19974. heightSegments: heightSegments,
  19975. openEnded: openEnded,
  19976. thetaStart: thetaStart,
  19977. thetaLength: thetaLength
  19978. }
  19979. const scope = this
  19980. radialSegments = Math.floor(radialSegments)
  19981. heightSegments = Math.floor(heightSegments)
  19982. // buffers
  19983. const indices = []
  19984. const vertices = []
  19985. const normals = []
  19986. const uvs = []
  19987. // helper variables
  19988. let index = 0
  19989. const indexArray = []
  19990. const halfHeight = height / 2
  19991. let groupStart = 0
  19992. // generate geometry
  19993. generateTorso()
  19994. if (openEnded === false) {
  19995. if (radiusTop > 0) generateCap(true)
  19996. if (radiusBottom > 0) generateCap(false)
  19997. }
  19998. // build geometry
  19999. this.setIndex(indices)
  20000. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  20001. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  20002. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  20003. function generateTorso() {
  20004. const normal = new Vector3()
  20005. const vertex = new Vector3()
  20006. let groupCount = 0
  20007. // this will be used to calculate the normal
  20008. const slope = (radiusBottom - radiusTop) / height
  20009. // generate vertices, normals and uvs
  20010. for (let y = 0; y <= heightSegments; y++) {
  20011. const indexRow = []
  20012. const v = y / heightSegments
  20013. // calculate the radius of the current row
  20014. const radius = v * (radiusBottom - radiusTop) + radiusTop
  20015. for (let x = 0; x <= radialSegments; x++) {
  20016. const u = x / radialSegments
  20017. const theta = u * thetaLength + thetaStart
  20018. const sinTheta = Math.sin(theta)
  20019. const cosTheta = Math.cos(theta)
  20020. // vertex
  20021. vertex.x = radius * sinTheta
  20022. vertex.y = -v * height + halfHeight
  20023. vertex.z = radius * cosTheta
  20024. vertices.push(vertex.x, vertex.y, vertex.z)
  20025. // normal
  20026. normal.set(sinTheta, slope, cosTheta).normalize()
  20027. normals.push(normal.x, normal.y, normal.z)
  20028. // uv
  20029. uvs.push(u, 1 - v)
  20030. // save index of vertex in respective row
  20031. indexRow.push(index++)
  20032. }
  20033. // now save vertices of the row in our index array
  20034. indexArray.push(indexRow)
  20035. }
  20036. // generate indices
  20037. for (let x = 0; x < radialSegments; x++) {
  20038. for (let y = 0; y < heightSegments; y++) {
  20039. // we use the index array to access the correct indices
  20040. const a = indexArray[y][x]
  20041. const b = indexArray[y + 1][x]
  20042. const c = indexArray[y + 1][x + 1]
  20043. const d = indexArray[y][x + 1]
  20044. // faces
  20045. indices.push(a, b, d)
  20046. indices.push(b, c, d)
  20047. // update group counter
  20048. groupCount += 6
  20049. }
  20050. }
  20051. // add a group to the geometry. this will ensure multi material support
  20052. scope.addGroup(groupStart, groupCount, 0)
  20053. // calculate new start value for groups
  20054. groupStart += groupCount
  20055. }
  20056. function generateCap(top) {
  20057. // save the index of the first center vertex
  20058. const centerIndexStart = index
  20059. const uv = new Vector2()
  20060. const vertex = new Vector3()
  20061. let groupCount = 0
  20062. const radius = top === true ? radiusTop : radiusBottom
  20063. const sign = top === true ? 1 : -1
  20064. // first we generate the center vertex data of the cap.
  20065. // because the geometry needs one set of uvs per face,
  20066. // we must generate a center vertex per face/segment
  20067. for (let x = 1; x <= radialSegments; x++) {
  20068. // vertex
  20069. vertices.push(0, halfHeight * sign, 0)
  20070. // normal
  20071. normals.push(0, sign, 0)
  20072. // uv
  20073. uvs.push(0.5, 0.5)
  20074. // increase index
  20075. index++
  20076. }
  20077. // save the index of the last center vertex
  20078. const centerIndexEnd = index
  20079. // now we generate the surrounding vertices, normals and uvs
  20080. for (let x = 0; x <= radialSegments; x++) {
  20081. const u = x / radialSegments
  20082. const theta = u * thetaLength + thetaStart
  20083. const cosTheta = Math.cos(theta)
  20084. const sinTheta = Math.sin(theta)
  20085. // vertex
  20086. vertex.x = radius * sinTheta
  20087. vertex.y = halfHeight * sign
  20088. vertex.z = radius * cosTheta
  20089. vertices.push(vertex.x, vertex.y, vertex.z)
  20090. // normal
  20091. normals.push(0, sign, 0)
  20092. // uv
  20093. uv.x = cosTheta * 0.5 + 0.5
  20094. uv.y = sinTheta * 0.5 * sign + 0.5
  20095. uvs.push(uv.x, uv.y)
  20096. // increase index
  20097. index++
  20098. }
  20099. // generate indices
  20100. for (let x = 0; x < radialSegments; x++) {
  20101. const c = centerIndexStart + x
  20102. const i = centerIndexEnd + x
  20103. if (top === true) {
  20104. // face top
  20105. indices.push(i, i + 1, c)
  20106. } else {
  20107. // face bottom
  20108. indices.push(i + 1, i, c)
  20109. }
  20110. groupCount += 3
  20111. }
  20112. // add a group to the geometry. this will ensure multi material support
  20113. scope.addGroup(groupStart, groupCount, top === true ? 1 : 2)
  20114. // calculate new start value for groups
  20115. groupStart += groupCount
  20116. }
  20117. }
  20118. static fromJSON(data) {
  20119. return new CylinderGeometry(data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength)
  20120. }
  20121. }
  20122. class ConeGeometry extends CylinderGeometry {
  20123. constructor(radius = 1, height = 1, radialSegments = 8, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
  20124. super(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength)
  20125. this.type = 'ConeGeometry'
  20126. this.parameters = {
  20127. radius: radius,
  20128. height: height,
  20129. radialSegments: radialSegments,
  20130. heightSegments: heightSegments,
  20131. openEnded: openEnded,
  20132. thetaStart: thetaStart,
  20133. thetaLength: thetaLength
  20134. }
  20135. }
  20136. static fromJSON(data) {
  20137. return new ConeGeometry(data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength)
  20138. }
  20139. }
  20140. class PolyhedronGeometry extends BufferGeometry {
  20141. constructor(vertices = [], indices = [], radius = 1, detail = 0) {
  20142. super()
  20143. this.type = 'PolyhedronGeometry'
  20144. this.parameters = {
  20145. vertices: vertices,
  20146. indices: indices,
  20147. radius: radius,
  20148. detail: detail
  20149. }
  20150. // default buffer data
  20151. const vertexBuffer = []
  20152. const uvBuffer = []
  20153. // the subdivision creates the vertex buffer data
  20154. subdivide(detail)
  20155. // all vertices should lie on a conceptual sphere with a given radius
  20156. applyRadius(radius)
  20157. // finally, create the uv data
  20158. generateUVs()
  20159. // build non-indexed geometry
  20160. this.setAttribute('position', new Float32BufferAttribute(vertexBuffer, 3))
  20161. this.setAttribute('normal', new Float32BufferAttribute(vertexBuffer.slice(), 3))
  20162. this.setAttribute('uv', new Float32BufferAttribute(uvBuffer, 2))
  20163. if (detail === 0) {
  20164. this.computeVertexNormals() // flat normals
  20165. } else {
  20166. this.normalizeNormals() // smooth normals
  20167. }
  20168. // helper functions
  20169. function subdivide(detail) {
  20170. const a = new Vector3()
  20171. const b = new Vector3()
  20172. const c = new Vector3()
  20173. // iterate over all faces and apply a subdivison with the given detail value
  20174. for (let i = 0; i < indices.length; i += 3) {
  20175. // get the vertices of the face
  20176. getVertexByIndex(indices[i + 0], a)
  20177. getVertexByIndex(indices[i + 1], b)
  20178. getVertexByIndex(indices[i + 2], c)
  20179. // perform subdivision
  20180. subdivideFace(a, b, c, detail)
  20181. }
  20182. }
  20183. function subdivideFace(a, b, c, detail) {
  20184. const cols = detail + 1
  20185. // we use this multidimensional array as a data structure for creating the subdivision
  20186. const v = []
  20187. // construct all of the vertices for this subdivision
  20188. for (let i = 0; i <= cols; i++) {
  20189. v[i] = []
  20190. const aj = a.clone().lerp(c, i / cols)
  20191. const bj = b.clone().lerp(c, i / cols)
  20192. const rows = cols - i
  20193. for (let j = 0; j <= rows; j++) {
  20194. if (j === 0 && i === cols) {
  20195. v[i][j] = aj
  20196. } else {
  20197. v[i][j] = aj.clone().lerp(bj, j / rows)
  20198. }
  20199. }
  20200. }
  20201. // construct all of the faces
  20202. for (let i = 0; i < cols; i++) {
  20203. for (let j = 0; j < 2 * (cols - i) - 1; j++) {
  20204. const k = Math.floor(j / 2)
  20205. if (j % 2 === 0) {
  20206. pushVertex(v[i][k + 1])
  20207. pushVertex(v[i + 1][k])
  20208. pushVertex(v[i][k])
  20209. } else {
  20210. pushVertex(v[i][k + 1])
  20211. pushVertex(v[i + 1][k + 1])
  20212. pushVertex(v[i + 1][k])
  20213. }
  20214. }
  20215. }
  20216. }
  20217. function applyRadius(radius) {
  20218. const vertex = new Vector3()
  20219. // iterate over the entire buffer and apply the radius to each vertex
  20220. for (let i = 0; i < vertexBuffer.length; i += 3) {
  20221. vertex.x = vertexBuffer[i + 0]
  20222. vertex.y = vertexBuffer[i + 1]
  20223. vertex.z = vertexBuffer[i + 2]
  20224. vertex.normalize().multiplyScalar(radius)
  20225. vertexBuffer[i + 0] = vertex.x
  20226. vertexBuffer[i + 1] = vertex.y
  20227. vertexBuffer[i + 2] = vertex.z
  20228. }
  20229. }
  20230. function generateUVs() {
  20231. const vertex = new Vector3()
  20232. for (let i = 0; i < vertexBuffer.length; i += 3) {
  20233. vertex.x = vertexBuffer[i + 0]
  20234. vertex.y = vertexBuffer[i + 1]
  20235. vertex.z = vertexBuffer[i + 2]
  20236. const u = azimuth(vertex) / 2 / Math.PI + 0.5
  20237. const v = inclination(vertex) / Math.PI + 0.5
  20238. uvBuffer.push(u, 1 - v)
  20239. }
  20240. correctUVs()
  20241. correctSeam()
  20242. }
  20243. function correctSeam() {
  20244. // handle case when face straddles the seam, see #3269
  20245. for (let i = 0; i < uvBuffer.length; i += 6) {
  20246. // uv data of a single face
  20247. const x0 = uvBuffer[i + 0]
  20248. const x1 = uvBuffer[i + 2]
  20249. const x2 = uvBuffer[i + 4]
  20250. const max = Math.max(x0, x1, x2)
  20251. const min = Math.min(x0, x1, x2)
  20252. // 0.9 is somewhat arbitrary
  20253. if (max > 0.9 && min < 0.1) {
  20254. if (x0 < 0.2) uvBuffer[i + 0] += 1
  20255. if (x1 < 0.2) uvBuffer[i + 2] += 1
  20256. if (x2 < 0.2) uvBuffer[i + 4] += 1
  20257. }
  20258. }
  20259. }
  20260. function pushVertex(vertex) {
  20261. vertexBuffer.push(vertex.x, vertex.y, vertex.z)
  20262. }
  20263. function getVertexByIndex(index, vertex) {
  20264. const stride = index * 3
  20265. vertex.x = vertices[stride + 0]
  20266. vertex.y = vertices[stride + 1]
  20267. vertex.z = vertices[stride + 2]
  20268. }
  20269. function correctUVs() {
  20270. const a = new Vector3()
  20271. const b = new Vector3()
  20272. const c = new Vector3()
  20273. const centroid = new Vector3()
  20274. const uvA = new Vector2()
  20275. const uvB = new Vector2()
  20276. const uvC = new Vector2()
  20277. for (let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6) {
  20278. a.set(vertexBuffer[i + 0], vertexBuffer[i + 1], vertexBuffer[i + 2])
  20279. b.set(vertexBuffer[i + 3], vertexBuffer[i + 4], vertexBuffer[i + 5])
  20280. c.set(vertexBuffer[i + 6], vertexBuffer[i + 7], vertexBuffer[i + 8])
  20281. uvA.set(uvBuffer[j + 0], uvBuffer[j + 1])
  20282. uvB.set(uvBuffer[j + 2], uvBuffer[j + 3])
  20283. uvC.set(uvBuffer[j + 4], uvBuffer[j + 5])
  20284. centroid
  20285. .copy(a)
  20286. .add(b)
  20287. .add(c)
  20288. .divideScalar(3)
  20289. const azi = azimuth(centroid)
  20290. correctUV(uvA, j + 0, a, azi)
  20291. correctUV(uvB, j + 2, b, azi)
  20292. correctUV(uvC, j + 4, c, azi)
  20293. }
  20294. }
  20295. function correctUV(uv, stride, vector, azimuth) {
  20296. if (azimuth < 0 && uv.x === 1) {
  20297. uvBuffer[stride] = uv.x - 1
  20298. }
  20299. if (vector.x === 0 && vector.z === 0) {
  20300. uvBuffer[stride] = azimuth / 2 / Math.PI + 0.5
  20301. }
  20302. }
  20303. // Angle around the Y axis, counter-clockwise when looking from above.
  20304. function azimuth(vector) {
  20305. return Math.atan2(vector.z, -vector.x)
  20306. }
  20307. // Angle above the XZ plane.
  20308. function inclination(vector) {
  20309. return Math.atan2(-vector.y, Math.sqrt(vector.x * vector.x + vector.z * vector.z))
  20310. }
  20311. }
  20312. static fromJSON(data) {
  20313. return new PolyhedronGeometry(data.vertices, data.indices, data.radius, data.details)
  20314. }
  20315. }
  20316. class DodecahedronGeometry extends PolyhedronGeometry {
  20317. constructor(radius = 1, detail = 0) {
  20318. const t = (1 + Math.sqrt(5)) / 2
  20319. const r = 1 / t
  20320. const vertices = [
  20321. // (±1, ±1, ±1)
  20322. -1,
  20323. -1,
  20324. -1,
  20325. -1,
  20326. -1,
  20327. 1,
  20328. -1,
  20329. 1,
  20330. -1,
  20331. -1,
  20332. 1,
  20333. 1,
  20334. 1,
  20335. -1,
  20336. -1,
  20337. 1,
  20338. -1,
  20339. 1,
  20340. 1,
  20341. 1,
  20342. -1,
  20343. 1,
  20344. 1,
  20345. 1,
  20346. // (0, ±1/φ, ±φ)
  20347. 0,
  20348. -r,
  20349. -t,
  20350. 0,
  20351. -r,
  20352. t,
  20353. 0,
  20354. r,
  20355. -t,
  20356. 0,
  20357. r,
  20358. t,
  20359. // (±1/φ, ±φ, 0)
  20360. -r,
  20361. -t,
  20362. 0,
  20363. -r,
  20364. t,
  20365. 0,
  20366. r,
  20367. -t,
  20368. 0,
  20369. r,
  20370. t,
  20371. 0,
  20372. // (±φ, 0, ±1/φ)
  20373. -t,
  20374. 0,
  20375. -r,
  20376. t,
  20377. 0,
  20378. -r,
  20379. -t,
  20380. 0,
  20381. r,
  20382. t,
  20383. 0,
  20384. r
  20385. ]
  20386. const indices = [
  20387. 3,
  20388. 11,
  20389. 7,
  20390. 3,
  20391. 7,
  20392. 15,
  20393. 3,
  20394. 15,
  20395. 13,
  20396. 7,
  20397. 19,
  20398. 17,
  20399. 7,
  20400. 17,
  20401. 6,
  20402. 7,
  20403. 6,
  20404. 15,
  20405. 17,
  20406. 4,
  20407. 8,
  20408. 17,
  20409. 8,
  20410. 10,
  20411. 17,
  20412. 10,
  20413. 6,
  20414. 8,
  20415. 0,
  20416. 16,
  20417. 8,
  20418. 16,
  20419. 2,
  20420. 8,
  20421. 2,
  20422. 10,
  20423. 0,
  20424. 12,
  20425. 1,
  20426. 0,
  20427. 1,
  20428. 18,
  20429. 0,
  20430. 18,
  20431. 16,
  20432. 6,
  20433. 10,
  20434. 2,
  20435. 6,
  20436. 2,
  20437. 13,
  20438. 6,
  20439. 13,
  20440. 15,
  20441. 2,
  20442. 16,
  20443. 18,
  20444. 2,
  20445. 18,
  20446. 3,
  20447. 2,
  20448. 3,
  20449. 13,
  20450. 18,
  20451. 1,
  20452. 9,
  20453. 18,
  20454. 9,
  20455. 11,
  20456. 18,
  20457. 11,
  20458. 3,
  20459. 4,
  20460. 14,
  20461. 12,
  20462. 4,
  20463. 12,
  20464. 0,
  20465. 4,
  20466. 0,
  20467. 8,
  20468. 11,
  20469. 9,
  20470. 5,
  20471. 11,
  20472. 5,
  20473. 19,
  20474. 11,
  20475. 19,
  20476. 7,
  20477. 19,
  20478. 5,
  20479. 14,
  20480. 19,
  20481. 14,
  20482. 4,
  20483. 19,
  20484. 4,
  20485. 17,
  20486. 1,
  20487. 12,
  20488. 14,
  20489. 1,
  20490. 14,
  20491. 5,
  20492. 1,
  20493. 5,
  20494. 9
  20495. ]
  20496. super(vertices, indices, radius, detail)
  20497. this.type = 'DodecahedronGeometry'
  20498. this.parameters = {
  20499. radius: radius,
  20500. detail: detail
  20501. }
  20502. }
  20503. static fromJSON(data) {
  20504. return new DodecahedronGeometry(data.radius, data.detail)
  20505. }
  20506. }
  20507. const _v0 = new Vector3()
  20508. const _v1$1 = new Vector3()
  20509. const _normal = new Vector3()
  20510. const _triangle = new Triangle()
  20511. class EdgesGeometry extends BufferGeometry {
  20512. constructor(geometry = null, thresholdAngle = 1) {
  20513. super()
  20514. this.type = 'EdgesGeometry'
  20515. this.parameters = {
  20516. geometry: geometry,
  20517. thresholdAngle: thresholdAngle
  20518. }
  20519. if (geometry !== null) {
  20520. const precisionPoints = 4
  20521. const precision = Math.pow(10, precisionPoints)
  20522. const thresholdDot = Math.cos(DEG2RAD * thresholdAngle)
  20523. const indexAttr = geometry.getIndex()
  20524. const positionAttr = geometry.getAttribute('position')
  20525. const indexCount = indexAttr ? indexAttr.count : positionAttr.count
  20526. const indexArr = [0, 0, 0]
  20527. const vertKeys = ['a', 'b', 'c']
  20528. const hashes = new Array(3)
  20529. const edgeData = {}
  20530. const vertices = []
  20531. for (let i = 0; i < indexCount; i += 3) {
  20532. if (indexAttr) {
  20533. indexArr[0] = indexAttr.getX(i)
  20534. indexArr[1] = indexAttr.getX(i + 1)
  20535. indexArr[2] = indexAttr.getX(i + 2)
  20536. } else {
  20537. indexArr[0] = i
  20538. indexArr[1] = i + 1
  20539. indexArr[2] = i + 2
  20540. }
  20541. const { a, b, c } = _triangle
  20542. a.fromBufferAttribute(positionAttr, indexArr[0])
  20543. b.fromBufferAttribute(positionAttr, indexArr[1])
  20544. c.fromBufferAttribute(positionAttr, indexArr[2])
  20545. _triangle.getNormal(_normal)
  20546. // create hashes for the edge from the vertices
  20547. hashes[0] = `${Math.round(a.x * precision)},${Math.round(a.y * precision)},${Math.round(a.z * precision)}`
  20548. hashes[1] = `${Math.round(b.x * precision)},${Math.round(b.y * precision)},${Math.round(b.z * precision)}`
  20549. hashes[2] = `${Math.round(c.x * precision)},${Math.round(c.y * precision)},${Math.round(c.z * precision)}`
  20550. // skip degenerate triangles
  20551. if (hashes[0] === hashes[1] || hashes[1] === hashes[2] || hashes[2] === hashes[0]) {
  20552. continue
  20553. }
  20554. // iterate over every edge
  20555. for (let j = 0; j < 3; j++) {
  20556. // get the first and next vertex making up the edge
  20557. const jNext = (j + 1) % 3
  20558. const vecHash0 = hashes[j]
  20559. const vecHash1 = hashes[jNext]
  20560. const v0 = _triangle[vertKeys[j]]
  20561. const v1 = _triangle[vertKeys[jNext]]
  20562. const hash = `${vecHash0}_${vecHash1}`
  20563. const reverseHash = `${vecHash1}_${vecHash0}`
  20564. if (reverseHash in edgeData && edgeData[reverseHash]) {
  20565. // if we found a sibling edge add it into the vertex array if
  20566. // it meets the angle threshold and delete the edge from the map.
  20567. if (_normal.dot(edgeData[reverseHash].normal) <= thresholdDot) {
  20568. vertices.push(v0.x, v0.y, v0.z)
  20569. vertices.push(v1.x, v1.y, v1.z)
  20570. }
  20571. edgeData[reverseHash] = null
  20572. } else if (!(hash in edgeData)) {
  20573. // if we've already got an edge here then skip adding a new one
  20574. edgeData[hash] = {
  20575. index0: indexArr[j],
  20576. index1: indexArr[jNext],
  20577. normal: _normal.clone()
  20578. }
  20579. }
  20580. }
  20581. }
  20582. // iterate over all remaining, unmatched edges and add them to the vertex array
  20583. for (const key in edgeData) {
  20584. if (edgeData[key]) {
  20585. const { index0, index1 } = edgeData[key]
  20586. _v0.fromBufferAttribute(positionAttr, index0)
  20587. _v1$1.fromBufferAttribute(positionAttr, index1)
  20588. vertices.push(_v0.x, _v0.y, _v0.z)
  20589. vertices.push(_v1$1.x, _v1$1.y, _v1$1.z)
  20590. }
  20591. }
  20592. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  20593. }
  20594. }
  20595. }
  20596. class Shape extends Path {
  20597. constructor(points) {
  20598. super(points)
  20599. this.uuid = generateUUID()
  20600. this.type = 'Shape'
  20601. this.holes = []
  20602. }
  20603. getPointsHoles(divisions) {
  20604. const holesPts = []
  20605. for (let i = 0, l = this.holes.length; i < l; i++) {
  20606. holesPts[i] = this.holes[i].getPoints(divisions)
  20607. }
  20608. return holesPts
  20609. }
  20610. // get points of shape and holes (keypoints based on segments parameter)
  20611. extractPoints(divisions) {
  20612. return {
  20613. shape: this.getPoints(divisions),
  20614. holes: this.getPointsHoles(divisions)
  20615. }
  20616. }
  20617. copy(source) {
  20618. super.copy(source)
  20619. this.holes = []
  20620. for (let i = 0, l = source.holes.length; i < l; i++) {
  20621. const hole = source.holes[i]
  20622. this.holes.push(hole.clone())
  20623. }
  20624. return this
  20625. }
  20626. toJSON() {
  20627. const data = super.toJSON()
  20628. data.uuid = this.uuid
  20629. data.holes = []
  20630. for (let i = 0, l = this.holes.length; i < l; i++) {
  20631. const hole = this.holes[i]
  20632. data.holes.push(hole.toJSON())
  20633. }
  20634. return data
  20635. }
  20636. fromJSON(json) {
  20637. super.fromJSON(json)
  20638. this.uuid = json.uuid
  20639. this.holes = []
  20640. for (let i = 0, l = json.holes.length; i < l; i++) {
  20641. const hole = json.holes[i]
  20642. this.holes.push(new Path().fromJSON(hole))
  20643. }
  20644. return this
  20645. }
  20646. }
  20647. /**
  20648. * Port from https://github.com/mapbox/earcut (v2.2.2)
  20649. */
  20650. const Earcut = {
  20651. triangulate: function(data, holeIndices, dim = 2) {
  20652. const hasHoles = holeIndices && holeIndices.length
  20653. const outerLen = hasHoles ? holeIndices[0] * dim : data.length
  20654. let outerNode = linkedList(data, 0, outerLen, dim, true)
  20655. const triangles = []
  20656. if (!outerNode || outerNode.next === outerNode.prev) return triangles
  20657. let minX, minY, maxX, maxY, x, y, invSize
  20658. if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim)
  20659. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  20660. if (data.length > 80 * dim) {
  20661. minX = maxX = data[0]
  20662. minY = maxY = data[1]
  20663. for (let i = dim; i < outerLen; i += dim) {
  20664. x = data[i]
  20665. y = data[i + 1]
  20666. if (x < minX) minX = x
  20667. if (y < minY) minY = y
  20668. if (x > maxX) maxX = x
  20669. if (y > maxY) maxY = y
  20670. }
  20671. // minX, minY and invSize are later used to transform coords into integers for z-order calculation
  20672. invSize = Math.max(maxX - minX, maxY - minY)
  20673. invSize = invSize !== 0 ? 1 / invSize : 0
  20674. }
  20675. earcutLinked(outerNode, triangles, dim, minX, minY, invSize)
  20676. return triangles
  20677. }
  20678. }
  20679. // create a circular doubly linked list from polygon points in the specified winding order
  20680. function linkedList(data, start, end, dim, clockwise) {
  20681. let i, last
  20682. if (clockwise === signedArea(data, start, end, dim) > 0) {
  20683. for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last)
  20684. } else {
  20685. for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last)
  20686. }
  20687. if (last && equals(last, last.next)) {
  20688. removeNode(last)
  20689. last = last.next
  20690. }
  20691. return last
  20692. }
  20693. // eliminate colinear or duplicate points
  20694. function filterPoints(start, end) {
  20695. if (!start) return start
  20696. if (!end) end = start
  20697. let p = start,
  20698. again
  20699. do {
  20700. again = false
  20701. if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
  20702. removeNode(p)
  20703. p = end = p.prev
  20704. if (p === p.next) break
  20705. again = true
  20706. } else {
  20707. p = p.next
  20708. }
  20709. } while (again || p !== end)
  20710. return end
  20711. }
  20712. // main ear slicing loop which triangulates a polygon (given as a linked list)
  20713. function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
  20714. if (!ear) return
  20715. // interlink polygon nodes in z-order
  20716. if (!pass && invSize) indexCurve(ear, minX, minY, invSize)
  20717. let stop = ear,
  20718. prev,
  20719. next
  20720. // iterate through ears, slicing them one by one
  20721. while (ear.prev !== ear.next) {
  20722. prev = ear.prev
  20723. next = ear.next
  20724. if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
  20725. // cut off the triangle
  20726. triangles.push(prev.i / dim)
  20727. triangles.push(ear.i / dim)
  20728. triangles.push(next.i / dim)
  20729. removeNode(ear)
  20730. // skipping the next vertex leads to less sliver triangles
  20731. ear = next.next
  20732. stop = next.next
  20733. continue
  20734. }
  20735. ear = next
  20736. // if we looped through the whole remaining polygon and can't find any more ears
  20737. if (ear === stop) {
  20738. // try filtering points and slicing again
  20739. if (!pass) {
  20740. earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1)
  20741. // if this didn't work, try curing all small self-intersections locally
  20742. } else if (pass === 1) {
  20743. ear = cureLocalIntersections(filterPoints(ear), triangles, dim)
  20744. earcutLinked(ear, triangles, dim, minX, minY, invSize, 2)
  20745. // as a last resort, try splitting the remaining polygon into two
  20746. } else if (pass === 2) {
  20747. splitEarcut(ear, triangles, dim, minX, minY, invSize)
  20748. }
  20749. break
  20750. }
  20751. }
  20752. }
  20753. // check whether a polygon node forms a valid ear with adjacent nodes
  20754. function isEar(ear) {
  20755. const a = ear.prev,
  20756. b = ear,
  20757. c = ear.next
  20758. if (area(a, b, c) >= 0) return false // reflex, can't be an ear
  20759. // now make sure we don't have other points inside the potential ear
  20760. let p = ear.next.next
  20761. while (p !== ear.prev) {
  20762. if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false
  20763. p = p.next
  20764. }
  20765. return true
  20766. }
  20767. function isEarHashed(ear, minX, minY, invSize) {
  20768. const a = ear.prev,
  20769. b = ear,
  20770. c = ear.next
  20771. if (area(a, b, c) >= 0) return false // reflex, can't be an ear
  20772. // triangle bbox; min & max are calculated like this for speed
  20773. const minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : b.x < c.x ? b.x : c.x,
  20774. minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : b.y < c.y ? b.y : c.y,
  20775. maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : b.x > c.x ? b.x : c.x,
  20776. maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : b.y > c.y ? b.y : c.y
  20777. // z-order range for the current triangle bbox;
  20778. const minZ = zOrder(minTX, minTY, minX, minY, invSize),
  20779. maxZ = zOrder(maxTX, maxTY, minX, minY, invSize)
  20780. let p = ear.prevZ,
  20781. n = ear.nextZ
  20782. // look for points inside the triangle in both directions
  20783. while (p && p.z >= minZ && n && n.z <= maxZ) {
  20784. if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false
  20785. p = p.prevZ
  20786. if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false
  20787. n = n.nextZ
  20788. }
  20789. // look for remaining points in decreasing z-order
  20790. while (p && p.z >= minZ) {
  20791. if (p !== ear.prev && p !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false
  20792. p = p.prevZ
  20793. }
  20794. // look for remaining points in increasing z-order
  20795. while (n && n.z <= maxZ) {
  20796. if (n !== ear.prev && n !== ear.next && pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false
  20797. n = n.nextZ
  20798. }
  20799. return true
  20800. }
  20801. // go through all polygon nodes and cure small local self-intersections
  20802. function cureLocalIntersections(start, triangles, dim) {
  20803. let p = start
  20804. do {
  20805. const a = p.prev,
  20806. b = p.next.next
  20807. if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
  20808. triangles.push(a.i / dim)
  20809. triangles.push(p.i / dim)
  20810. triangles.push(b.i / dim)
  20811. // remove two nodes involved
  20812. removeNode(p)
  20813. removeNode(p.next)
  20814. p = start = b
  20815. }
  20816. p = p.next
  20817. } while (p !== start)
  20818. return filterPoints(p)
  20819. }
  20820. // try splitting polygon into two and triangulate them independently
  20821. function splitEarcut(start, triangles, dim, minX, minY, invSize) {
  20822. // look for a valid diagonal that divides the polygon into two
  20823. let a = start
  20824. do {
  20825. let b = a.next.next
  20826. while (b !== a.prev) {
  20827. if (a.i !== b.i && isValidDiagonal(a, b)) {
  20828. // split the polygon in two by the diagonal
  20829. let c = splitPolygon(a, b)
  20830. // filter colinear points around the cuts
  20831. a = filterPoints(a, a.next)
  20832. c = filterPoints(c, c.next)
  20833. // run earcut on each half
  20834. earcutLinked(a, triangles, dim, minX, minY, invSize)
  20835. earcutLinked(c, triangles, dim, minX, minY, invSize)
  20836. return
  20837. }
  20838. b = b.next
  20839. }
  20840. a = a.next
  20841. } while (a !== start)
  20842. }
  20843. // link every hole into the outer loop, producing a single-ring polygon without holes
  20844. function eliminateHoles(data, holeIndices, outerNode, dim) {
  20845. const queue = []
  20846. let i, len, start, end, list
  20847. for (i = 0, len = holeIndices.length; i < len; i++) {
  20848. start = holeIndices[i] * dim
  20849. end = i < len - 1 ? holeIndices[i + 1] * dim : data.length
  20850. list = linkedList(data, start, end, dim, false)
  20851. if (list === list.next) list.steiner = true
  20852. queue.push(getLeftmost(list))
  20853. }
  20854. queue.sort(compareX)
  20855. // process holes from left to right
  20856. for (i = 0; i < queue.length; i++) {
  20857. eliminateHole(queue[i], outerNode)
  20858. outerNode = filterPoints(outerNode, outerNode.next)
  20859. }
  20860. return outerNode
  20861. }
  20862. function compareX(a, b) {
  20863. return a.x - b.x
  20864. }
  20865. // find a bridge between vertices that connects hole with an outer ring and link it
  20866. function eliminateHole(hole, outerNode) {
  20867. outerNode = findHoleBridge(hole, outerNode)
  20868. if (outerNode) {
  20869. const b = splitPolygon(outerNode, hole)
  20870. // filter collinear points around the cuts
  20871. filterPoints(outerNode, outerNode.next)
  20872. filterPoints(b, b.next)
  20873. }
  20874. }
  20875. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  20876. function findHoleBridge(hole, outerNode) {
  20877. let p = outerNode
  20878. const hx = hole.x
  20879. const hy = hole.y
  20880. let qx = -Infinity,
  20881. m
  20882. // find a segment intersected by a ray from the hole's leftmost point to the left;
  20883. // segment's endpoint with lesser x will be potential connection point
  20884. do {
  20885. if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
  20886. const x = p.x + ((hy - p.y) * (p.next.x - p.x)) / (p.next.y - p.y)
  20887. if (x <= hx && x > qx) {
  20888. qx = x
  20889. if (x === hx) {
  20890. if (hy === p.y) return p
  20891. if (hy === p.next.y) return p.next
  20892. }
  20893. m = p.x < p.next.x ? p : p.next
  20894. }
  20895. }
  20896. p = p.next
  20897. } while (p !== outerNode)
  20898. if (!m) return null
  20899. if (hx === qx) return m // hole touches outer segment; pick leftmost endpoint
  20900. // look for points inside the triangle of hole point, segment intersection and endpoint;
  20901. // if there are no points found, we have a valid connection;
  20902. // otherwise choose the point of the minimum angle with the ray as connection point
  20903. const stop = m,
  20904. mx = m.x,
  20905. my = m.y
  20906. let tanMin = Infinity,
  20907. tan
  20908. p = m
  20909. do {
  20910. if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
  20911. tan = Math.abs(hy - p.y) / (hx - p.x) // tangential
  20912. if (locallyInside(p, hole) && (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
  20913. m = p
  20914. tanMin = tan
  20915. }
  20916. }
  20917. p = p.next
  20918. } while (p !== stop)
  20919. return m
  20920. }
  20921. // whether sector in vertex m contains sector in vertex p in the same coordinates
  20922. function sectorContainsSector(m, p) {
  20923. return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0
  20924. }
  20925. // interlink polygon nodes in z-order
  20926. function indexCurve(start, minX, minY, invSize) {
  20927. let p = start
  20928. do {
  20929. if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize)
  20930. p.prevZ = p.prev
  20931. p.nextZ = p.next
  20932. p = p.next
  20933. } while (p !== start)
  20934. p.prevZ.nextZ = null
  20935. p.prevZ = null
  20936. sortLinked(p)
  20937. }
  20938. // Simon Tatham's linked list merge sort algorithm
  20939. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  20940. function sortLinked(list) {
  20941. let i,
  20942. p,
  20943. q,
  20944. e,
  20945. tail,
  20946. numMerges,
  20947. pSize,
  20948. qSize,
  20949. inSize = 1
  20950. do {
  20951. p = list
  20952. list = null
  20953. tail = null
  20954. numMerges = 0
  20955. while (p) {
  20956. numMerges++
  20957. q = p
  20958. pSize = 0
  20959. for (i = 0; i < inSize; i++) {
  20960. pSize++
  20961. q = q.nextZ
  20962. if (!q) break
  20963. }
  20964. qSize = inSize
  20965. while (pSize > 0 || (qSize > 0 && q)) {
  20966. if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
  20967. e = p
  20968. p = p.nextZ
  20969. pSize--
  20970. } else {
  20971. e = q
  20972. q = q.nextZ
  20973. qSize--
  20974. }
  20975. if (tail) tail.nextZ = e
  20976. else list = e
  20977. e.prevZ = tail
  20978. tail = e
  20979. }
  20980. p = q
  20981. }
  20982. tail.nextZ = null
  20983. inSize *= 2
  20984. } while (numMerges > 1)
  20985. return list
  20986. }
  20987. // z-order of a point given coords and inverse of the longer side of data bbox
  20988. function zOrder(x, y, minX, minY, invSize) {
  20989. // coords are transformed into non-negative 15-bit integer range
  20990. x = 32767 * (x - minX) * invSize
  20991. y = 32767 * (y - minY) * invSize
  20992. x = (x | (x << 8)) & 0x00ff00ff
  20993. x = (x | (x << 4)) & 0x0f0f0f0f
  20994. x = (x | (x << 2)) & 0x33333333
  20995. x = (x | (x << 1)) & 0x55555555
  20996. y = (y | (y << 8)) & 0x00ff00ff
  20997. y = (y | (y << 4)) & 0x0f0f0f0f
  20998. y = (y | (y << 2)) & 0x33333333
  20999. y = (y | (y << 1)) & 0x55555555
  21000. return x | (y << 1)
  21001. }
  21002. // find the leftmost node of a polygon ring
  21003. function getLeftmost(start) {
  21004. let p = start,
  21005. leftmost = start
  21006. do {
  21007. if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p
  21008. p = p.next
  21009. } while (p !== start)
  21010. return leftmost
  21011. }
  21012. // check if a point lies within a convex triangle
  21013. function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
  21014. return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0
  21015. }
  21016. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  21017. function isValidDiagonal(a, b) {
  21018. return (
  21019. a.next.i !== b.i &&
  21020. a.prev.i !== b.i &&
  21021. !intersectsPolygon(a, b) && // doesn't intersect other edges
  21022. ((locallyInside(a, b) &&
  21023. locallyInside(b, a) &&
  21024. middleInside(a, b) && // locally visible
  21025. (area(a.prev, a, b.prev) || area(a, b.prev, b))) || // does not create opposite-facing sectors
  21026. (equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0))
  21027. ) // special zero-length case
  21028. }
  21029. // signed area of a triangle
  21030. function area(p, q, r) {
  21031. return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)
  21032. }
  21033. // check if two points are equal
  21034. function equals(p1, p2) {
  21035. return p1.x === p2.x && p1.y === p2.y
  21036. }
  21037. // check if two segments intersect
  21038. function intersects(p1, q1, p2, q2) {
  21039. const o1 = sign(area(p1, q1, p2))
  21040. const o2 = sign(area(p1, q1, q2))
  21041. const o3 = sign(area(p2, q2, p1))
  21042. const o4 = sign(area(p2, q2, q1))
  21043. if (o1 !== o2 && o3 !== o4) return true // general case
  21044. if (o1 === 0 && onSegment(p1, p2, q1)) return true // p1, q1 and p2 are collinear and p2 lies on p1q1
  21045. if (o2 === 0 && onSegment(p1, q2, q1)) return true // p1, q1 and q2 are collinear and q2 lies on p1q1
  21046. if (o3 === 0 && onSegment(p2, p1, q2)) return true // p2, q2 and p1 are collinear and p1 lies on p2q2
  21047. if (o4 === 0 && onSegment(p2, q1, q2)) return true // p2, q2 and q1 are collinear and q1 lies on p2q2
  21048. return false
  21049. }
  21050. // for collinear points p, q, r, check if point q lies on segment pr
  21051. function onSegment(p, q, r) {
  21052. return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y)
  21053. }
  21054. function sign(num) {
  21055. return num > 0 ? 1 : num < 0 ? -1 : 0
  21056. }
  21057. // check if a polygon diagonal intersects any polygon segments
  21058. function intersectsPolygon(a, b) {
  21059. let p = a
  21060. do {
  21061. if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true
  21062. p = p.next
  21063. } while (p !== a)
  21064. return false
  21065. }
  21066. // check if a polygon diagonal is locally inside the polygon
  21067. function locallyInside(a, b) {
  21068. return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0
  21069. }
  21070. // check if the middle point of a polygon diagonal is inside the polygon
  21071. function middleInside(a, b) {
  21072. let p = a,
  21073. inside = false
  21074. const px = (a.x + b.x) / 2,
  21075. py = (a.y + b.y) / 2
  21076. do {
  21077. if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < ((p.next.x - p.x) * (py - p.y)) / (p.next.y - p.y) + p.x) inside = !inside
  21078. p = p.next
  21079. } while (p !== a)
  21080. return inside
  21081. }
  21082. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
  21083. // if one belongs to the outer ring and another to a hole, it merges it into a single ring
  21084. function splitPolygon(a, b) {
  21085. const a2 = new Node(a.i, a.x, a.y),
  21086. b2 = new Node(b.i, b.x, b.y),
  21087. an = a.next,
  21088. bp = b.prev
  21089. a.next = b
  21090. b.prev = a
  21091. a2.next = an
  21092. an.prev = a2
  21093. b2.next = a2
  21094. a2.prev = b2
  21095. bp.next = b2
  21096. b2.prev = bp
  21097. return b2
  21098. }
  21099. // create a node and optionally link it with previous one (in a circular doubly linked list)
  21100. function insertNode(i, x, y, last) {
  21101. const p = new Node(i, x, y)
  21102. if (!last) {
  21103. p.prev = p
  21104. p.next = p
  21105. } else {
  21106. p.next = last.next
  21107. p.prev = last
  21108. last.next.prev = p
  21109. last.next = p
  21110. }
  21111. return p
  21112. }
  21113. function removeNode(p) {
  21114. p.next.prev = p.prev
  21115. p.prev.next = p.next
  21116. if (p.prevZ) p.prevZ.nextZ = p.nextZ
  21117. if (p.nextZ) p.nextZ.prevZ = p.prevZ
  21118. }
  21119. function Node(i, x, y) {
  21120. // vertex index in coordinates array
  21121. this.i = i
  21122. // vertex coordinates
  21123. this.x = x
  21124. this.y = y
  21125. // previous and next vertex nodes in a polygon ring
  21126. this.prev = null
  21127. this.next = null
  21128. // z-order curve value
  21129. this.z = null
  21130. // previous and next nodes in z-order
  21131. this.prevZ = null
  21132. this.nextZ = null
  21133. // indicates whether this is a steiner point
  21134. this.steiner = false
  21135. }
  21136. function signedArea(data, start, end, dim) {
  21137. let sum = 0
  21138. for (let i = start, j = end - dim; i < end; i += dim) {
  21139. sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1])
  21140. j = i
  21141. }
  21142. return sum
  21143. }
  21144. class ShapeUtils {
  21145. // calculate area of the contour polygon
  21146. static area(contour) {
  21147. const n = contour.length
  21148. let a = 0.0
  21149. for (let p = n - 1, q = 0; q < n; p = q++) {
  21150. a += contour[p].x * contour[q].y - contour[q].x * contour[p].y
  21151. }
  21152. return a * 0.5
  21153. }
  21154. static isClockWise(pts) {
  21155. return ShapeUtils.area(pts) < 0
  21156. }
  21157. static triangulateShape(contour, holes) {
  21158. const vertices = [] // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
  21159. const holeIndices = [] // array of hole indices
  21160. const faces = [] // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
  21161. removeDupEndPts(contour)
  21162. addContour(vertices, contour)
  21163. //
  21164. let holeIndex = contour.length
  21165. holes.forEach(removeDupEndPts)
  21166. for (let i = 0; i < holes.length; i++) {
  21167. holeIndices.push(holeIndex)
  21168. holeIndex += holes[i].length
  21169. addContour(vertices, holes[i])
  21170. }
  21171. //
  21172. const triangles = Earcut.triangulate(vertices, holeIndices)
  21173. //
  21174. for (let i = 0; i < triangles.length; i += 3) {
  21175. faces.push(triangles.slice(i, i + 3))
  21176. }
  21177. return faces
  21178. }
  21179. }
  21180. function removeDupEndPts(points) {
  21181. const l = points.length
  21182. if (l > 2 && points[l - 1].equals(points[0])) {
  21183. points.pop()
  21184. }
  21185. }
  21186. function addContour(vertices, contour) {
  21187. for (let i = 0; i < contour.length; i++) {
  21188. vertices.push(contour[i].x)
  21189. vertices.push(contour[i].y)
  21190. }
  21191. }
  21192. /**
  21193. * Creates extruded geometry from a path shape.
  21194. *
  21195. * parameters = {
  21196. *
  21197. * curveSegments: <int>, // number of points on the curves
  21198. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  21199. * depth: <float>, // Depth to extrude the shape
  21200. *
  21201. * bevelEnabled: <bool>, // turn on bevel
  21202. * bevelThickness: <float>, // how deep into the original shape bevel goes
  21203. * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
  21204. * bevelOffset: <float>, // how far from shape outline does bevel start
  21205. * bevelSegments: <int>, // number of bevel layers
  21206. *
  21207. * extrudePath: <THREE.Curve> // curve to extrude shape along
  21208. *
  21209. * UVGenerator: <Object> // object that provides UV generator functions
  21210. *
  21211. * }
  21212. */
  21213. class ExtrudeGeometry extends BufferGeometry {
  21214. constructor(shapes = new Shape([new Vector2(0.5, 0.5), new Vector2(-0.5, 0.5), new Vector2(-0.5, -0.5), new Vector2(0.5, -0.5)]), options = {}) {
  21215. super()
  21216. this.type = 'ExtrudeGeometry'
  21217. this.parameters = {
  21218. shapes: shapes,
  21219. options: options
  21220. }
  21221. shapes = Array.isArray(shapes) ? shapes : [shapes]
  21222. const scope = this
  21223. const verticesArray = []
  21224. const uvArray = []
  21225. for (let i = 0, l = shapes.length; i < l; i++) {
  21226. const shape = shapes[i]
  21227. addShape(shape)
  21228. }
  21229. // build geometry
  21230. this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3))
  21231. this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2))
  21232. this.computeVertexNormals()
  21233. // functions
  21234. function addShape(shape) {
  21235. const placeholder = []
  21236. // options
  21237. const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12
  21238. const steps = options.steps !== undefined ? options.steps : 1
  21239. let depth = options.depth !== undefined ? options.depth : 1
  21240. let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true
  21241. let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2
  21242. let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1
  21243. let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0
  21244. let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3
  21245. const extrudePath = options.extrudePath
  21246. const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator
  21247. // deprecated options
  21248. if (options.amount !== undefined) {
  21249. console.warn('THREE.ExtrudeBufferGeometry: amount has been renamed to depth.')
  21250. depth = options.amount
  21251. }
  21252. //
  21253. let extrudePts,
  21254. extrudeByPath = false
  21255. let splineTube, binormal, normal, position2
  21256. if (extrudePath) {
  21257. extrudePts = extrudePath.getSpacedPoints(steps)
  21258. extrudeByPath = true
  21259. bevelEnabled = false // bevels not supported for path extrusion
  21260. // SETUP TNB variables
  21261. // TODO1 - have a .isClosed in spline?
  21262. splineTube = extrudePath.computeFrenetFrames(steps, false)
  21263. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  21264. binormal = new Vector3()
  21265. normal = new Vector3()
  21266. position2 = new Vector3()
  21267. }
  21268. // Safeguards if bevels are not enabled
  21269. if (!bevelEnabled) {
  21270. bevelSegments = 0
  21271. bevelThickness = 0
  21272. bevelSize = 0
  21273. bevelOffset = 0
  21274. }
  21275. // Variables initialization
  21276. const shapePoints = shape.extractPoints(curveSegments)
  21277. let vertices = shapePoints.shape
  21278. const holes = shapePoints.holes
  21279. const reverse = !ShapeUtils.isClockWise(vertices)
  21280. if (reverse) {
  21281. vertices = vertices.reverse()
  21282. // Maybe we should also check if holes are in the opposite direction, just to be safe ...
  21283. for (let h = 0, hl = holes.length; h < hl; h++) {
  21284. const ahole = holes[h]
  21285. if (ShapeUtils.isClockWise(ahole)) {
  21286. holes[h] = ahole.reverse()
  21287. }
  21288. }
  21289. }
  21290. const faces = ShapeUtils.triangulateShape(vertices, holes)
  21291. /* Vertices */
  21292. const contour = vertices // vertices has all points but contour has only points of circumference
  21293. for (let h = 0, hl = holes.length; h < hl; h++) {
  21294. const ahole = holes[h]
  21295. vertices = vertices.concat(ahole)
  21296. }
  21297. function scalePt2(pt, vec, size) {
  21298. if (!vec) console.error('THREE.ExtrudeGeometry: vec does not exist')
  21299. return vec
  21300. .clone()
  21301. .multiplyScalar(size)
  21302. .add(pt)
  21303. }
  21304. const vlen = vertices.length,
  21305. flen = faces.length
  21306. // Find directions for point movement
  21307. function getBevelVec(inPt, inPrev, inNext) {
  21308. // computes for inPt the corresponding point inPt' on a new contour
  21309. // shifted by 1 unit (length of normalized vector) to the left
  21310. // if we walk along contour clockwise, this new contour is outside the old one
  21311. //
  21312. // inPt' is the intersection of the two lines parallel to the two
  21313. // adjacent edges of inPt at a distance of 1 unit on the left side.
  21314. let v_trans_x, v_trans_y, shrink_by // resulting translation vector for inPt
  21315. // good reading for geometry algorithms (here: line-line intersection)
  21316. // http://geomalgorithms.com/a05-_intersect-1.html
  21317. const v_prev_x = inPt.x - inPrev.x,
  21318. v_prev_y = inPt.y - inPrev.y
  21319. const v_next_x = inNext.x - inPt.x,
  21320. v_next_y = inNext.y - inPt.y
  21321. const v_prev_lensq = v_prev_x * v_prev_x + v_prev_y * v_prev_y
  21322. // check for collinear edges
  21323. const collinear0 = v_prev_x * v_next_y - v_prev_y * v_next_x
  21324. if (Math.abs(collinear0) > Number.EPSILON) {
  21325. // not collinear
  21326. // length of vectors for normalizing
  21327. const v_prev_len = Math.sqrt(v_prev_lensq)
  21328. const v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y)
  21329. // shift adjacent points by unit vectors to the left
  21330. const ptPrevShift_x = inPrev.x - v_prev_y / v_prev_len
  21331. const ptPrevShift_y = inPrev.y + v_prev_x / v_prev_len
  21332. const ptNextShift_x = inNext.x - v_next_y / v_next_len
  21333. const ptNextShift_y = inNext.y + v_next_x / v_next_len
  21334. // scaling factor for v_prev to intersection point
  21335. const sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x)
  21336. // vector from inPt to intersection point
  21337. v_trans_x = ptPrevShift_x + v_prev_x * sf - inPt.x
  21338. v_trans_y = ptPrevShift_y + v_prev_y * sf - inPt.y
  21339. // Don't normalize!, otherwise sharp corners become ugly
  21340. // but prevent crazy spikes
  21341. const v_trans_lensq = v_trans_x * v_trans_x + v_trans_y * v_trans_y
  21342. if (v_trans_lensq <= 2) {
  21343. return new Vector2(v_trans_x, v_trans_y)
  21344. } else {
  21345. shrink_by = Math.sqrt(v_trans_lensq / 2)
  21346. }
  21347. } else {
  21348. // handle special case of collinear edges
  21349. let direction_eq = false // assumes: opposite
  21350. if (v_prev_x > Number.EPSILON) {
  21351. if (v_next_x > Number.EPSILON) {
  21352. direction_eq = true
  21353. }
  21354. } else {
  21355. if (v_prev_x < -Number.EPSILON) {
  21356. if (v_next_x < -Number.EPSILON) {
  21357. direction_eq = true
  21358. }
  21359. } else {
  21360. if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
  21361. direction_eq = true
  21362. }
  21363. }
  21364. }
  21365. if (direction_eq) {
  21366. // console.log("Warning: lines are a straight sequence");
  21367. v_trans_x = -v_prev_y
  21368. v_trans_y = v_prev_x
  21369. shrink_by = Math.sqrt(v_prev_lensq)
  21370. } else {
  21371. // console.log("Warning: lines are a straight spike");
  21372. v_trans_x = v_prev_x
  21373. v_trans_y = v_prev_y
  21374. shrink_by = Math.sqrt(v_prev_lensq / 2)
  21375. }
  21376. }
  21377. return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by)
  21378. }
  21379. const contourMovements = []
  21380. for (let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
  21381. if (j === il) j = 0
  21382. if (k === il) k = 0
  21383. // (j)---(i)---(k)
  21384. // console.log('i,j,k', i, j , k)
  21385. contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k])
  21386. }
  21387. const holesMovements = []
  21388. let oneHoleMovements,
  21389. verticesMovements = contourMovements.concat()
  21390. for (let h = 0, hl = holes.length; h < hl; h++) {
  21391. const ahole = holes[h]
  21392. oneHoleMovements = []
  21393. for (let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
  21394. if (j === il) j = 0
  21395. if (k === il) k = 0
  21396. // (j)---(i)---(k)
  21397. oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k])
  21398. }
  21399. holesMovements.push(oneHoleMovements)
  21400. verticesMovements = verticesMovements.concat(oneHoleMovements)
  21401. }
  21402. // Loop bevelSegments, 1 for the front, 1 for the back
  21403. for (let b = 0; b < bevelSegments; b++) {
  21404. //for ( b = bevelSegments; b > 0; b -- ) {
  21405. const t = b / bevelSegments
  21406. const z = bevelThickness * Math.cos((t * Math.PI) / 2)
  21407. const bs = bevelSize * Math.sin((t * Math.PI) / 2) + bevelOffset
  21408. // contract shape
  21409. for (let i = 0, il = contour.length; i < il; i++) {
  21410. const vert = scalePt2(contour[i], contourMovements[i], bs)
  21411. v(vert.x, vert.y, -z)
  21412. }
  21413. // expand holes
  21414. for (let h = 0, hl = holes.length; h < hl; h++) {
  21415. const ahole = holes[h]
  21416. oneHoleMovements = holesMovements[h]
  21417. for (let i = 0, il = ahole.length; i < il; i++) {
  21418. const vert = scalePt2(ahole[i], oneHoleMovements[i], bs)
  21419. v(vert.x, vert.y, -z)
  21420. }
  21421. }
  21422. }
  21423. const bs = bevelSize + bevelOffset
  21424. // Back facing vertices
  21425. for (let i = 0; i < vlen; i++) {
  21426. const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]
  21427. if (!extrudeByPath) {
  21428. v(vert.x, vert.y, 0)
  21429. } else {
  21430. // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  21431. normal.copy(splineTube.normals[0]).multiplyScalar(vert.x)
  21432. binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y)
  21433. position2
  21434. .copy(extrudePts[0])
  21435. .add(normal)
  21436. .add(binormal)
  21437. v(position2.x, position2.y, position2.z)
  21438. }
  21439. }
  21440. // Add stepped vertices...
  21441. // Including front facing vertices
  21442. for (let s = 1; s <= steps; s++) {
  21443. for (let i = 0; i < vlen; i++) {
  21444. const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i]
  21445. if (!extrudeByPath) {
  21446. v(vert.x, vert.y, (depth / steps) * s)
  21447. } else {
  21448. // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  21449. normal.copy(splineTube.normals[s]).multiplyScalar(vert.x)
  21450. binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y)
  21451. position2
  21452. .copy(extrudePts[s])
  21453. .add(normal)
  21454. .add(binormal)
  21455. v(position2.x, position2.y, position2.z)
  21456. }
  21457. }
  21458. }
  21459. // Add bevel segments planes
  21460. //for ( b = 1; b <= bevelSegments; b ++ ) {
  21461. for (let b = bevelSegments - 1; b >= 0; b--) {
  21462. const t = b / bevelSegments
  21463. const z = bevelThickness * Math.cos((t * Math.PI) / 2)
  21464. const bs = bevelSize * Math.sin((t * Math.PI) / 2) + bevelOffset
  21465. // contract shape
  21466. for (let i = 0, il = contour.length; i < il; i++) {
  21467. const vert = scalePt2(contour[i], contourMovements[i], bs)
  21468. v(vert.x, vert.y, depth + z)
  21469. }
  21470. // expand holes
  21471. for (let h = 0, hl = holes.length; h < hl; h++) {
  21472. const ahole = holes[h]
  21473. oneHoleMovements = holesMovements[h]
  21474. for (let i = 0, il = ahole.length; i < il; i++) {
  21475. const vert = scalePt2(ahole[i], oneHoleMovements[i], bs)
  21476. if (!extrudeByPath) {
  21477. v(vert.x, vert.y, depth + z)
  21478. } else {
  21479. v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z)
  21480. }
  21481. }
  21482. }
  21483. }
  21484. /* Faces */
  21485. // Top and bottom faces
  21486. buildLidFaces()
  21487. // Sides faces
  21488. buildSideFaces()
  21489. ///// Internal functions
  21490. function buildLidFaces() {
  21491. const start = verticesArray.length / 3
  21492. if (bevelEnabled) {
  21493. let layer = 0 // steps + 1
  21494. let offset = vlen * layer
  21495. // Bottom faces
  21496. for (let i = 0; i < flen; i++) {
  21497. const face = faces[i]
  21498. f3(face[2] + offset, face[1] + offset, face[0] + offset)
  21499. }
  21500. layer = steps + bevelSegments * 2
  21501. offset = vlen * layer
  21502. // Top faces
  21503. for (let i = 0; i < flen; i++) {
  21504. const face = faces[i]
  21505. f3(face[0] + offset, face[1] + offset, face[2] + offset)
  21506. }
  21507. } else {
  21508. // Bottom faces
  21509. for (let i = 0; i < flen; i++) {
  21510. const face = faces[i]
  21511. f3(face[2], face[1], face[0])
  21512. }
  21513. // Top faces
  21514. for (let i = 0; i < flen; i++) {
  21515. const face = faces[i]
  21516. f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps)
  21517. }
  21518. }
  21519. scope.addGroup(start, verticesArray.length / 3 - start, 0)
  21520. }
  21521. // Create faces for the z-sides of the shape
  21522. function buildSideFaces() {
  21523. const start = verticesArray.length / 3
  21524. let layeroffset = 0
  21525. sidewalls(contour, layeroffset)
  21526. layeroffset += contour.length
  21527. for (let h = 0, hl = holes.length; h < hl; h++) {
  21528. const ahole = holes[h]
  21529. sidewalls(ahole, layeroffset)
  21530. //, true
  21531. layeroffset += ahole.length
  21532. }
  21533. scope.addGroup(start, verticesArray.length / 3 - start, 1)
  21534. }
  21535. function sidewalls(contour, layeroffset) {
  21536. let i = contour.length
  21537. while (--i >= 0) {
  21538. const j = i
  21539. let k = i - 1
  21540. if (k < 0) k = contour.length - 1
  21541. //console.log('b', i,j, i-1, k,vertices.length);
  21542. for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
  21543. const slen1 = vlen * s
  21544. const slen2 = vlen * (s + 1)
  21545. const a = layeroffset + j + slen1,
  21546. b = layeroffset + k + slen1,
  21547. c = layeroffset + k + slen2,
  21548. d = layeroffset + j + slen2
  21549. f4(a, b, c, d)
  21550. }
  21551. }
  21552. }
  21553. function v(x, y, z) {
  21554. placeholder.push(x)
  21555. placeholder.push(y)
  21556. placeholder.push(z)
  21557. }
  21558. function f3(a, b, c) {
  21559. addVertex(a)
  21560. addVertex(b)
  21561. addVertex(c)
  21562. const nextIndex = verticesArray.length / 3
  21563. const uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1)
  21564. addUV(uvs[0])
  21565. addUV(uvs[1])
  21566. addUV(uvs[2])
  21567. }
  21568. function f4(a, b, c, d) {
  21569. addVertex(a)
  21570. addVertex(b)
  21571. addVertex(d)
  21572. addVertex(b)
  21573. addVertex(c)
  21574. addVertex(d)
  21575. const nextIndex = verticesArray.length / 3
  21576. const uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1)
  21577. addUV(uvs[0])
  21578. addUV(uvs[1])
  21579. addUV(uvs[3])
  21580. addUV(uvs[1])
  21581. addUV(uvs[2])
  21582. addUV(uvs[3])
  21583. }
  21584. function addVertex(index) {
  21585. verticesArray.push(placeholder[index * 3 + 0])
  21586. verticesArray.push(placeholder[index * 3 + 1])
  21587. verticesArray.push(placeholder[index * 3 + 2])
  21588. }
  21589. function addUV(vector2) {
  21590. uvArray.push(vector2.x)
  21591. uvArray.push(vector2.y)
  21592. }
  21593. }
  21594. }
  21595. toJSON() {
  21596. const data = super.toJSON()
  21597. const shapes = this.parameters.shapes
  21598. const options = this.parameters.options
  21599. return toJSON$1(shapes, options, data)
  21600. }
  21601. static fromJSON(data, shapes) {
  21602. const geometryShapes = []
  21603. for (let j = 0, jl = data.shapes.length; j < jl; j++) {
  21604. const shape = shapes[data.shapes[j]]
  21605. geometryShapes.push(shape)
  21606. }
  21607. const extrudePath = data.options.extrudePath
  21608. if (extrudePath !== undefined) {
  21609. data.options.extrudePath = new Curves[extrudePath.type]().fromJSON(extrudePath)
  21610. }
  21611. return new ExtrudeGeometry(geometryShapes, data.options)
  21612. }
  21613. }
  21614. const WorldUVGenerator = {
  21615. generateTopUV: function(geometry, vertices, indexA, indexB, indexC) {
  21616. const a_x = vertices[indexA * 3]
  21617. const a_y = vertices[indexA * 3 + 1]
  21618. const b_x = vertices[indexB * 3]
  21619. const b_y = vertices[indexB * 3 + 1]
  21620. const c_x = vertices[indexC * 3]
  21621. const c_y = vertices[indexC * 3 + 1]
  21622. return [new Vector2(a_x, a_y), new Vector2(b_x, b_y), new Vector2(c_x, c_y)]
  21623. },
  21624. generateSideWallUV: function(geometry, vertices, indexA, indexB, indexC, indexD) {
  21625. const a_x = vertices[indexA * 3]
  21626. const a_y = vertices[indexA * 3 + 1]
  21627. const a_z = vertices[indexA * 3 + 2]
  21628. const b_x = vertices[indexB * 3]
  21629. const b_y = vertices[indexB * 3 + 1]
  21630. const b_z = vertices[indexB * 3 + 2]
  21631. const c_x = vertices[indexC * 3]
  21632. const c_y = vertices[indexC * 3 + 1]
  21633. const c_z = vertices[indexC * 3 + 2]
  21634. const d_x = vertices[indexD * 3]
  21635. const d_y = vertices[indexD * 3 + 1]
  21636. const d_z = vertices[indexD * 3 + 2]
  21637. if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) {
  21638. return [new Vector2(a_x, 1 - a_z), new Vector2(b_x, 1 - b_z), new Vector2(c_x, 1 - c_z), new Vector2(d_x, 1 - d_z)]
  21639. } else {
  21640. return [new Vector2(a_y, 1 - a_z), new Vector2(b_y, 1 - b_z), new Vector2(c_y, 1 - c_z), new Vector2(d_y, 1 - d_z)]
  21641. }
  21642. }
  21643. }
  21644. function toJSON$1(shapes, options, data) {
  21645. data.shapes = []
  21646. if (Array.isArray(shapes)) {
  21647. for (let i = 0, l = shapes.length; i < l; i++) {
  21648. const shape = shapes[i]
  21649. data.shapes.push(shape.uuid)
  21650. }
  21651. } else {
  21652. data.shapes.push(shapes.uuid)
  21653. }
  21654. data.options = Object.assign({}, options)
  21655. if (options.extrudePath !== undefined) data.options.extrudePath = options.extrudePath.toJSON()
  21656. return data
  21657. }
  21658. class IcosahedronGeometry extends PolyhedronGeometry {
  21659. constructor(radius = 1, detail = 0) {
  21660. const t = (1 + Math.sqrt(5)) / 2
  21661. const vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, 0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1]
  21662. const indices = [
  21663. 0,
  21664. 11,
  21665. 5,
  21666. 0,
  21667. 5,
  21668. 1,
  21669. 0,
  21670. 1,
  21671. 7,
  21672. 0,
  21673. 7,
  21674. 10,
  21675. 0,
  21676. 10,
  21677. 11,
  21678. 1,
  21679. 5,
  21680. 9,
  21681. 5,
  21682. 11,
  21683. 4,
  21684. 11,
  21685. 10,
  21686. 2,
  21687. 10,
  21688. 7,
  21689. 6,
  21690. 7,
  21691. 1,
  21692. 8,
  21693. 3,
  21694. 9,
  21695. 4,
  21696. 3,
  21697. 4,
  21698. 2,
  21699. 3,
  21700. 2,
  21701. 6,
  21702. 3,
  21703. 6,
  21704. 8,
  21705. 3,
  21706. 8,
  21707. 9,
  21708. 4,
  21709. 9,
  21710. 5,
  21711. 2,
  21712. 4,
  21713. 11,
  21714. 6,
  21715. 2,
  21716. 10,
  21717. 8,
  21718. 6,
  21719. 7,
  21720. 9,
  21721. 8,
  21722. 1
  21723. ]
  21724. super(vertices, indices, radius, detail)
  21725. this.type = 'IcosahedronGeometry'
  21726. this.parameters = {
  21727. radius: radius,
  21728. detail: detail
  21729. }
  21730. }
  21731. static fromJSON(data) {
  21732. return new IcosahedronGeometry(data.radius, data.detail)
  21733. }
  21734. }
  21735. class OctahedronGeometry extends PolyhedronGeometry {
  21736. constructor(radius = 1, detail = 0) {
  21737. const vertices = [1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1]
  21738. const indices = [0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2]
  21739. super(vertices, indices, radius, detail)
  21740. this.type = 'OctahedronGeometry'
  21741. this.parameters = {
  21742. radius: radius,
  21743. detail: detail
  21744. }
  21745. }
  21746. static fromJSON(data) {
  21747. return new OctahedronGeometry(data.radius, data.detail)
  21748. }
  21749. }
  21750. class RingGeometry extends BufferGeometry {
  21751. constructor(innerRadius = 0.5, outerRadius = 1, thetaSegments = 8, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
  21752. super()
  21753. this.type = 'RingGeometry'
  21754. this.parameters = {
  21755. innerRadius: innerRadius,
  21756. outerRadius: outerRadius,
  21757. thetaSegments: thetaSegments,
  21758. phiSegments: phiSegments,
  21759. thetaStart: thetaStart,
  21760. thetaLength: thetaLength
  21761. }
  21762. thetaSegments = Math.max(3, thetaSegments)
  21763. phiSegments = Math.max(1, phiSegments)
  21764. // buffers
  21765. const indices = []
  21766. const vertices = []
  21767. const normals = []
  21768. const uvs = []
  21769. // some helper variables
  21770. let radius = innerRadius
  21771. const radiusStep = (outerRadius - innerRadius) / phiSegments
  21772. const vertex = new Vector3()
  21773. const uv = new Vector2()
  21774. // generate vertices, normals and uvs
  21775. for (let j = 0; j <= phiSegments; j++) {
  21776. for (let i = 0; i <= thetaSegments; i++) {
  21777. // values are generate from the inside of the ring to the outside
  21778. const segment = thetaStart + (i / thetaSegments) * thetaLength
  21779. // vertex
  21780. vertex.x = radius * Math.cos(segment)
  21781. vertex.y = radius * Math.sin(segment)
  21782. vertices.push(vertex.x, vertex.y, vertex.z)
  21783. // normal
  21784. normals.push(0, 0, 1)
  21785. // uv
  21786. uv.x = (vertex.x / outerRadius + 1) / 2
  21787. uv.y = (vertex.y / outerRadius + 1) / 2
  21788. uvs.push(uv.x, uv.y)
  21789. }
  21790. // increase the radius for next row of vertices
  21791. radius += radiusStep
  21792. }
  21793. // indices
  21794. for (let j = 0; j < phiSegments; j++) {
  21795. const thetaSegmentLevel = j * (thetaSegments + 1)
  21796. for (let i = 0; i < thetaSegments; i++) {
  21797. const segment = i + thetaSegmentLevel
  21798. const a = segment
  21799. const b = segment + thetaSegments + 1
  21800. const c = segment + thetaSegments + 2
  21801. const d = segment + 1
  21802. // faces
  21803. indices.push(a, b, d)
  21804. indices.push(b, c, d)
  21805. }
  21806. }
  21807. // build geometry
  21808. this.setIndex(indices)
  21809. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  21810. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  21811. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  21812. }
  21813. static fromJSON(data) {
  21814. return new RingGeometry(data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength)
  21815. }
  21816. }
  21817. class ShapeGeometry extends BufferGeometry {
  21818. constructor(shapes = new Shape([new Vector2(0, 0.5), new Vector2(-0.5, -0.5), new Vector2(0.5, -0.5)]), curveSegments = 12) {
  21819. super()
  21820. this.type = 'ShapeGeometry'
  21821. this.parameters = {
  21822. shapes: shapes,
  21823. curveSegments: curveSegments
  21824. }
  21825. // buffers
  21826. const indices = []
  21827. const vertices = []
  21828. const normals = []
  21829. const uvs = []
  21830. // helper variables
  21831. let groupStart = 0
  21832. let groupCount = 0
  21833. // allow single and array values for "shapes" parameter
  21834. if (Array.isArray(shapes) === false) {
  21835. addShape(shapes)
  21836. } else {
  21837. for (let i = 0; i < shapes.length; i++) {
  21838. addShape(shapes[i])
  21839. this.addGroup(groupStart, groupCount, i) // enables MultiMaterial support
  21840. groupStart += groupCount
  21841. groupCount = 0
  21842. }
  21843. }
  21844. // build geometry
  21845. this.setIndex(indices)
  21846. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  21847. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  21848. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  21849. // helper functions
  21850. function addShape(shape) {
  21851. const indexOffset = vertices.length / 3
  21852. const points = shape.extractPoints(curveSegments)
  21853. let shapeVertices = points.shape
  21854. const shapeHoles = points.holes
  21855. // check direction of vertices
  21856. if (ShapeUtils.isClockWise(shapeVertices) === false) {
  21857. shapeVertices = shapeVertices.reverse()
  21858. }
  21859. for (let i = 0, l = shapeHoles.length; i < l; i++) {
  21860. const shapeHole = shapeHoles[i]
  21861. if (ShapeUtils.isClockWise(shapeHole) === true) {
  21862. shapeHoles[i] = shapeHole.reverse()
  21863. }
  21864. }
  21865. const faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles)
  21866. // join vertices of inner and outer paths to a single array
  21867. for (let i = 0, l = shapeHoles.length; i < l; i++) {
  21868. const shapeHole = shapeHoles[i]
  21869. shapeVertices = shapeVertices.concat(shapeHole)
  21870. }
  21871. // vertices, normals, uvs
  21872. for (let i = 0, l = shapeVertices.length; i < l; i++) {
  21873. const vertex = shapeVertices[i]
  21874. vertices.push(vertex.x, vertex.y, 0)
  21875. normals.push(0, 0, 1)
  21876. uvs.push(vertex.x, vertex.y) // world uvs
  21877. }
  21878. // incides
  21879. for (let i = 0, l = faces.length; i < l; i++) {
  21880. const face = faces[i]
  21881. const a = face[0] + indexOffset
  21882. const b = face[1] + indexOffset
  21883. const c = face[2] + indexOffset
  21884. indices.push(a, b, c)
  21885. groupCount += 3
  21886. }
  21887. }
  21888. }
  21889. toJSON() {
  21890. const data = super.toJSON()
  21891. const shapes = this.parameters.shapes
  21892. return toJSON(shapes, data)
  21893. }
  21894. static fromJSON(data, shapes) {
  21895. const geometryShapes = []
  21896. for (let j = 0, jl = data.shapes.length; j < jl; j++) {
  21897. const shape = shapes[data.shapes[j]]
  21898. geometryShapes.push(shape)
  21899. }
  21900. return new ShapeGeometry(geometryShapes, data.curveSegments)
  21901. }
  21902. }
  21903. function toJSON(shapes, data) {
  21904. data.shapes = []
  21905. if (Array.isArray(shapes)) {
  21906. for (let i = 0, l = shapes.length; i < l; i++) {
  21907. const shape = shapes[i]
  21908. data.shapes.push(shape.uuid)
  21909. }
  21910. } else {
  21911. data.shapes.push(shapes.uuid)
  21912. }
  21913. return data
  21914. }
  21915. class SphereGeometry extends BufferGeometry {
  21916. constructor(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
  21917. super()
  21918. this.type = 'SphereGeometry'
  21919. this.parameters = {
  21920. radius: radius,
  21921. widthSegments: widthSegments,
  21922. heightSegments: heightSegments,
  21923. phiStart: phiStart,
  21924. phiLength: phiLength,
  21925. thetaStart: thetaStart,
  21926. thetaLength: thetaLength
  21927. }
  21928. widthSegments = Math.max(3, Math.floor(widthSegments))
  21929. heightSegments = Math.max(2, Math.floor(heightSegments))
  21930. const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI)
  21931. let index = 0
  21932. const grid = []
  21933. const vertex = new Vector3()
  21934. const normal = new Vector3()
  21935. // buffers
  21936. const indices = []
  21937. const vertices = []
  21938. const normals = []
  21939. const uvs = []
  21940. // generate vertices, normals and uvs
  21941. for (let iy = 0; iy <= heightSegments; iy++) {
  21942. const verticesRow = []
  21943. const v = iy / heightSegments
  21944. // special case for the poles
  21945. let uOffset = 0
  21946. if (iy == 0 && thetaStart == 0) {
  21947. uOffset = 0.5 / widthSegments
  21948. } else if (iy == heightSegments && thetaEnd == Math.PI) {
  21949. uOffset = -0.5 / widthSegments
  21950. }
  21951. for (let ix = 0; ix <= widthSegments; ix++) {
  21952. const u = ix / widthSegments
  21953. // vertex
  21954. vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength)
  21955. vertex.y = radius * Math.cos(thetaStart + v * thetaLength)
  21956. vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength)
  21957. vertices.push(vertex.x, vertex.y, vertex.z)
  21958. // normal
  21959. normal.copy(vertex).normalize()
  21960. normals.push(normal.x, normal.y, normal.z)
  21961. // uv
  21962. uvs.push(u + uOffset, 1 - v)
  21963. verticesRow.push(index++)
  21964. }
  21965. grid.push(verticesRow)
  21966. }
  21967. // indices
  21968. for (let iy = 0; iy < heightSegments; iy++) {
  21969. for (let ix = 0; ix < widthSegments; ix++) {
  21970. const a = grid[iy][ix + 1]
  21971. const b = grid[iy][ix]
  21972. const c = grid[iy + 1][ix]
  21973. const d = grid[iy + 1][ix + 1]
  21974. if (iy !== 0 || thetaStart > 0) indices.push(a, b, d)
  21975. if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d)
  21976. }
  21977. }
  21978. // build geometry
  21979. this.setIndex(indices)
  21980. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  21981. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  21982. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  21983. }
  21984. static fromJSON(data) {
  21985. return new SphereGeometry(data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength)
  21986. }
  21987. }
  21988. class TetrahedronGeometry extends PolyhedronGeometry {
  21989. constructor(radius = 1, detail = 0) {
  21990. const vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1]
  21991. const indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1]
  21992. super(vertices, indices, radius, detail)
  21993. this.type = 'TetrahedronGeometry'
  21994. this.parameters = {
  21995. radius: radius,
  21996. detail: detail
  21997. }
  21998. }
  21999. static fromJSON(data) {
  22000. return new TetrahedronGeometry(data.radius, data.detail)
  22001. }
  22002. }
  22003. class TorusGeometry extends BufferGeometry {
  22004. constructor(radius = 1, tube = 0.4, radialSegments = 8, tubularSegments = 6, arc = Math.PI * 2) {
  22005. super()
  22006. this.type = 'TorusGeometry'
  22007. this.parameters = {
  22008. radius: radius,
  22009. tube: tube,
  22010. radialSegments: radialSegments,
  22011. tubularSegments: tubularSegments,
  22012. arc: arc
  22013. }
  22014. radialSegments = Math.floor(radialSegments)
  22015. tubularSegments = Math.floor(tubularSegments)
  22016. // buffers
  22017. const indices = []
  22018. const vertices = []
  22019. const normals = []
  22020. const uvs = []
  22021. // helper variables
  22022. const center = new Vector3()
  22023. const vertex = new Vector3()
  22024. const normal = new Vector3()
  22025. // generate vertices, normals and uvs
  22026. for (let j = 0; j <= radialSegments; j++) {
  22027. for (let i = 0; i <= tubularSegments; i++) {
  22028. const u = (i / tubularSegments) * arc
  22029. const v = (j / radialSegments) * Math.PI * 2
  22030. // vertex
  22031. vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u)
  22032. vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u)
  22033. vertex.z = tube * Math.sin(v)
  22034. vertices.push(vertex.x, vertex.y, vertex.z)
  22035. // normal
  22036. center.x = radius * Math.cos(u)
  22037. center.y = radius * Math.sin(u)
  22038. normal.subVectors(vertex, center).normalize()
  22039. normals.push(normal.x, normal.y, normal.z)
  22040. // uv
  22041. uvs.push(i / tubularSegments)
  22042. uvs.push(j / radialSegments)
  22043. }
  22044. }
  22045. // generate indices
  22046. for (let j = 1; j <= radialSegments; j++) {
  22047. for (let i = 1; i <= tubularSegments; i++) {
  22048. // indices
  22049. const a = (tubularSegments + 1) * j + i - 1
  22050. const b = (tubularSegments + 1) * (j - 1) + i - 1
  22051. const c = (tubularSegments + 1) * (j - 1) + i
  22052. const d = (tubularSegments + 1) * j + i
  22053. // faces
  22054. indices.push(a, b, d)
  22055. indices.push(b, c, d)
  22056. }
  22057. }
  22058. // build geometry
  22059. this.setIndex(indices)
  22060. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  22061. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  22062. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  22063. }
  22064. static fromJSON(data) {
  22065. return new TorusGeometry(data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc)
  22066. }
  22067. }
  22068. class TorusKnotGeometry extends BufferGeometry {
  22069. constructor(radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3) {
  22070. super()
  22071. this.type = 'TorusKnotGeometry'
  22072. this.parameters = {
  22073. radius: radius,
  22074. tube: tube,
  22075. tubularSegments: tubularSegments,
  22076. radialSegments: radialSegments,
  22077. p: p,
  22078. q: q
  22079. }
  22080. tubularSegments = Math.floor(tubularSegments)
  22081. radialSegments = Math.floor(radialSegments)
  22082. // buffers
  22083. const indices = []
  22084. const vertices = []
  22085. const normals = []
  22086. const uvs = []
  22087. // helper variables
  22088. const vertex = new Vector3()
  22089. const normal = new Vector3()
  22090. const P1 = new Vector3()
  22091. const P2 = new Vector3()
  22092. const B = new Vector3()
  22093. const T = new Vector3()
  22094. const N = new Vector3()
  22095. // generate vertices, normals and uvs
  22096. for (let i = 0; i <= tubularSegments; ++i) {
  22097. // the radian "u" is used to calculate the position on the torus curve of the current tubular segment
  22098. const u = (i / tubularSegments) * p * Math.PI * 2
  22099. // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
  22100. // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
  22101. calculatePositionOnCurve(u, p, q, radius, P1)
  22102. calculatePositionOnCurve(u + 0.01, p, q, radius, P2)
  22103. // calculate orthonormal basis
  22104. T.subVectors(P2, P1)
  22105. N.addVectors(P2, P1)
  22106. B.crossVectors(T, N)
  22107. N.crossVectors(B, T)
  22108. // normalize B, N. T can be ignored, we don't use it
  22109. B.normalize()
  22110. N.normalize()
  22111. for (let j = 0; j <= radialSegments; ++j) {
  22112. // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
  22113. // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
  22114. const v = (j / radialSegments) * Math.PI * 2
  22115. const cx = -tube * Math.cos(v)
  22116. const cy = tube * Math.sin(v)
  22117. // now calculate the final vertex position.
  22118. // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
  22119. vertex.x = P1.x + (cx * N.x + cy * B.x)
  22120. vertex.y = P1.y + (cx * N.y + cy * B.y)
  22121. vertex.z = P1.z + (cx * N.z + cy * B.z)
  22122. vertices.push(vertex.x, vertex.y, vertex.z)
  22123. // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
  22124. normal.subVectors(vertex, P1).normalize()
  22125. normals.push(normal.x, normal.y, normal.z)
  22126. // uv
  22127. uvs.push(i / tubularSegments)
  22128. uvs.push(j / radialSegments)
  22129. }
  22130. }
  22131. // generate indices
  22132. for (let j = 1; j <= tubularSegments; j++) {
  22133. for (let i = 1; i <= radialSegments; i++) {
  22134. // indices
  22135. const a = (radialSegments + 1) * (j - 1) + (i - 1)
  22136. const b = (radialSegments + 1) * j + (i - 1)
  22137. const c = (radialSegments + 1) * j + i
  22138. const d = (radialSegments + 1) * (j - 1) + i
  22139. // faces
  22140. indices.push(a, b, d)
  22141. indices.push(b, c, d)
  22142. }
  22143. }
  22144. // build geometry
  22145. this.setIndex(indices)
  22146. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  22147. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  22148. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  22149. // this function calculates the current position on the torus curve
  22150. function calculatePositionOnCurve(u, p, q, radius, position) {
  22151. const cu = Math.cos(u)
  22152. const su = Math.sin(u)
  22153. const quOverP = (q / p) * u
  22154. const cs = Math.cos(quOverP)
  22155. position.x = radius * (2 + cs) * 0.5 * cu
  22156. position.y = radius * (2 + cs) * su * 0.5
  22157. position.z = radius * Math.sin(quOverP) * 0.5
  22158. }
  22159. }
  22160. static fromJSON(data) {
  22161. return new TorusKnotGeometry(data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q)
  22162. }
  22163. }
  22164. class TubeGeometry extends BufferGeometry {
  22165. constructor(path = new QuadraticBezierCurve3(new Vector3(-1, -1, 0), new Vector3(-1, 1, 0), new Vector3(1, 1, 0)), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false) {
  22166. super()
  22167. this.type = 'TubeGeometry'
  22168. this.parameters = {
  22169. path: path,
  22170. tubularSegments: tubularSegments,
  22171. radius: radius,
  22172. radialSegments: radialSegments,
  22173. closed: closed
  22174. }
  22175. const frames = path.computeFrenetFrames(tubularSegments, closed)
  22176. // expose internals
  22177. this.tangents = frames.tangents
  22178. this.normals = frames.normals
  22179. this.binormals = frames.binormals
  22180. // helper variables
  22181. const vertex = new Vector3()
  22182. const normal = new Vector3()
  22183. const uv = new Vector2()
  22184. let P = new Vector3()
  22185. // buffer
  22186. const vertices = []
  22187. const normals = []
  22188. const uvs = []
  22189. const indices = []
  22190. // create buffer data
  22191. generateBufferData()
  22192. // build geometry
  22193. this.setIndex(indices)
  22194. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  22195. this.setAttribute('normal', new Float32BufferAttribute(normals, 3))
  22196. this.setAttribute('uv', new Float32BufferAttribute(uvs, 2))
  22197. // functions
  22198. function generateBufferData() {
  22199. for (let i = 0; i < tubularSegments; i++) {
  22200. generateSegment(i)
  22201. }
  22202. // if the geometry is not closed, generate the last row of vertices and normals
  22203. // at the regular position on the given path
  22204. //
  22205. // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
  22206. generateSegment(closed === false ? tubularSegments : 0)
  22207. // uvs are generated in a separate function.
  22208. // this makes it easy compute correct values for closed geometries
  22209. generateUVs()
  22210. // finally create faces
  22211. generateIndices()
  22212. }
  22213. function generateSegment(i) {
  22214. // we use getPointAt to sample evenly distributed points from the given path
  22215. P = path.getPointAt(i / tubularSegments, P)
  22216. // retrieve corresponding normal and binormal
  22217. const N = frames.normals[i]
  22218. const B = frames.binormals[i]
  22219. // generate normals and vertices for the current segment
  22220. for (let j = 0; j <= radialSegments; j++) {
  22221. const v = (j / radialSegments) * Math.PI * 2
  22222. const sin = Math.sin(v)
  22223. const cos = -Math.cos(v)
  22224. // normal
  22225. normal.x = cos * N.x + sin * B.x
  22226. normal.y = cos * N.y + sin * B.y
  22227. normal.z = cos * N.z + sin * B.z
  22228. normal.normalize()
  22229. normals.push(normal.x, normal.y, normal.z)
  22230. // vertex
  22231. vertex.x = P.x + radius * normal.x
  22232. vertex.y = P.y + radius * normal.y
  22233. vertex.z = P.z + radius * normal.z
  22234. vertices.push(vertex.x, vertex.y, vertex.z)
  22235. }
  22236. }
  22237. function generateIndices() {
  22238. for (let j = 1; j <= tubularSegments; j++) {
  22239. for (let i = 1; i <= radialSegments; i++) {
  22240. const a = (radialSegments + 1) * (j - 1) + (i - 1)
  22241. const b = (radialSegments + 1) * j + (i - 1)
  22242. const c = (radialSegments + 1) * j + i
  22243. const d = (radialSegments + 1) * (j - 1) + i
  22244. // faces
  22245. indices.push(a, b, d)
  22246. indices.push(b, c, d)
  22247. }
  22248. }
  22249. }
  22250. function generateUVs() {
  22251. for (let i = 0; i <= tubularSegments; i++) {
  22252. for (let j = 0; j <= radialSegments; j++) {
  22253. uv.x = i / tubularSegments
  22254. uv.y = j / radialSegments
  22255. uvs.push(uv.x, uv.y)
  22256. }
  22257. }
  22258. }
  22259. }
  22260. toJSON() {
  22261. const data = super.toJSON()
  22262. data.path = this.parameters.path.toJSON()
  22263. return data
  22264. }
  22265. static fromJSON(data) {
  22266. // This only works for built-in curves (e.g. CatmullRomCurve3).
  22267. // User defined curves or instances of CurvePath will not be deserialized.
  22268. return new TubeGeometry(new Curves[data.path.type]().fromJSON(data.path), data.tubularSegments, data.radius, data.radialSegments, data.closed)
  22269. }
  22270. }
  22271. class WireframeGeometry extends BufferGeometry {
  22272. constructor(geometry = null) {
  22273. super()
  22274. this.type = 'WireframeGeometry'
  22275. this.parameters = {
  22276. geometry: geometry
  22277. }
  22278. if (geometry !== null) {
  22279. // buffer
  22280. const vertices = []
  22281. const edges = new Set()
  22282. // helper variables
  22283. const start = new Vector3()
  22284. const end = new Vector3()
  22285. if (geometry.index !== null) {
  22286. // indexed BufferGeometry
  22287. const position = geometry.attributes.position
  22288. const indices = geometry.index
  22289. let groups = geometry.groups
  22290. if (groups.length === 0) {
  22291. groups = [{ start: 0, count: indices.count, materialIndex: 0 }]
  22292. }
  22293. // create a data structure that contains all edges without duplicates
  22294. for (let o = 0, ol = groups.length; o < ol; ++o) {
  22295. const group = groups[o]
  22296. const groupStart = group.start
  22297. const groupCount = group.count
  22298. for (let i = groupStart, l = groupStart + groupCount; i < l; i += 3) {
  22299. for (let j = 0; j < 3; j++) {
  22300. const index1 = indices.getX(i + j)
  22301. const index2 = indices.getX(i + ((j + 1) % 3))
  22302. start.fromBufferAttribute(position, index1)
  22303. end.fromBufferAttribute(position, index2)
  22304. if (isUniqueEdge(start, end, edges) === true) {
  22305. vertices.push(start.x, start.y, start.z)
  22306. vertices.push(end.x, end.y, end.z)
  22307. }
  22308. }
  22309. }
  22310. }
  22311. } else {
  22312. // non-indexed BufferGeometry
  22313. const position = geometry.attributes.position
  22314. for (let i = 0, l = position.count / 3; i < l; i++) {
  22315. for (let j = 0; j < 3; j++) {
  22316. // three edges per triangle, an edge is represented as (index1, index2)
  22317. // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
  22318. const index1 = 3 * i + j
  22319. const index2 = 3 * i + ((j + 1) % 3)
  22320. start.fromBufferAttribute(position, index1)
  22321. end.fromBufferAttribute(position, index2)
  22322. if (isUniqueEdge(start, end, edges) === true) {
  22323. vertices.push(start.x, start.y, start.z)
  22324. vertices.push(end.x, end.y, end.z)
  22325. }
  22326. }
  22327. }
  22328. }
  22329. // build geometry
  22330. this.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  22331. }
  22332. }
  22333. }
  22334. function isUniqueEdge(start, end, edges) {
  22335. const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`
  22336. const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}` // coincident edge
  22337. if (edges.has(hash1) === true || edges.has(hash2) === true) {
  22338. return false
  22339. } else {
  22340. edges.add(hash1)
  22341. edges.add(hash2)
  22342. return true
  22343. }
  22344. }
  22345. var Geometries = /*#__PURE__*/ Object.freeze({
  22346. __proto__: null,
  22347. BoxGeometry: BoxGeometry,
  22348. BoxBufferGeometry: BoxGeometry,
  22349. CapsuleGeometry: CapsuleGeometry,
  22350. CapsuleBufferGeometry: CapsuleGeometry,
  22351. CircleGeometry: CircleGeometry,
  22352. CircleBufferGeometry: CircleGeometry,
  22353. ConeGeometry: ConeGeometry,
  22354. ConeBufferGeometry: ConeGeometry,
  22355. CylinderGeometry: CylinderGeometry,
  22356. CylinderBufferGeometry: CylinderGeometry,
  22357. DodecahedronGeometry: DodecahedronGeometry,
  22358. DodecahedronBufferGeometry: DodecahedronGeometry,
  22359. EdgesGeometry: EdgesGeometry,
  22360. ExtrudeGeometry: ExtrudeGeometry,
  22361. ExtrudeBufferGeometry: ExtrudeGeometry,
  22362. IcosahedronGeometry: IcosahedronGeometry,
  22363. IcosahedronBufferGeometry: IcosahedronGeometry,
  22364. LatheGeometry: LatheGeometry,
  22365. LatheBufferGeometry: LatheGeometry,
  22366. OctahedronGeometry: OctahedronGeometry,
  22367. OctahedronBufferGeometry: OctahedronGeometry,
  22368. PlaneGeometry: PlaneGeometry,
  22369. PlaneBufferGeometry: PlaneGeometry,
  22370. PolyhedronGeometry: PolyhedronGeometry,
  22371. PolyhedronBufferGeometry: PolyhedronGeometry,
  22372. RingGeometry: RingGeometry,
  22373. RingBufferGeometry: RingGeometry,
  22374. ShapeGeometry: ShapeGeometry,
  22375. ShapeBufferGeometry: ShapeGeometry,
  22376. SphereGeometry: SphereGeometry,
  22377. SphereBufferGeometry: SphereGeometry,
  22378. TetrahedronGeometry: TetrahedronGeometry,
  22379. TetrahedronBufferGeometry: TetrahedronGeometry,
  22380. TorusGeometry: TorusGeometry,
  22381. TorusBufferGeometry: TorusGeometry,
  22382. TorusKnotGeometry: TorusKnotGeometry,
  22383. TorusKnotBufferGeometry: TorusKnotGeometry,
  22384. TubeGeometry: TubeGeometry,
  22385. TubeBufferGeometry: TubeGeometry,
  22386. WireframeGeometry: WireframeGeometry
  22387. })
  22388. class ShadowMaterial extends Material {
  22389. constructor(parameters) {
  22390. super()
  22391. this.isShadowMaterial = true
  22392. this.type = 'ShadowMaterial'
  22393. this.color = new Color(0x000000)
  22394. this.transparent = true
  22395. this.fog = true
  22396. this.setValues(parameters)
  22397. }
  22398. copy(source) {
  22399. super.copy(source)
  22400. this.color.copy(source.color)
  22401. this.fog = source.fog
  22402. return this
  22403. }
  22404. }
  22405. class RawShaderMaterial extends ShaderMaterial {
  22406. constructor(parameters) {
  22407. super(parameters)
  22408. this.isRawShaderMaterial = true
  22409. this.type = 'RawShaderMaterial'
  22410. }
  22411. }
  22412. class MeshStandardMaterial extends Material {
  22413. constructor(parameters) {
  22414. super()
  22415. this.isMeshStandardMaterial = true
  22416. this.defines = { STANDARD: '' }
  22417. this.type = 'MeshStandardMaterial'
  22418. this.color = new Color(0xffffff) // diffuse
  22419. this.roughness = 1.0
  22420. this.metalness = 0.0
  22421. this.map = null
  22422. this.lightMap = null
  22423. this.lightMapIntensity = 1.0
  22424. this.aoMap = null
  22425. this.aoMapIntensity = 1.0
  22426. this.emissive = new Color(0x000000)
  22427. this.emissiveIntensity = 1.0
  22428. this.emissiveMap = null
  22429. this.bumpMap = null
  22430. this.bumpScale = 1
  22431. this.normalMap = null
  22432. this.normalMapType = TangentSpaceNormalMap
  22433. this.normalScale = new Vector2(1, 1)
  22434. this.displacementMap = null
  22435. this.displacementScale = 1
  22436. this.displacementBias = 0
  22437. this.roughnessMap = null
  22438. this.metalnessMap = null
  22439. this.alphaMap = null
  22440. this.envMap = null
  22441. this.envMapIntensity = 1.0
  22442. this.wireframe = false
  22443. this.wireframeLinewidth = 1
  22444. this.wireframeLinecap = 'round'
  22445. this.wireframeLinejoin = 'round'
  22446. this.flatShading = false
  22447. this.fog = true
  22448. this.setValues(parameters)
  22449. }
  22450. copy(source) {
  22451. super.copy(source)
  22452. this.defines = { STANDARD: '' }
  22453. this.color.copy(source.color)
  22454. this.roughness = source.roughness
  22455. this.metalness = source.metalness
  22456. this.map = source.map
  22457. this.lightMap = source.lightMap
  22458. this.lightMapIntensity = source.lightMapIntensity
  22459. this.aoMap = source.aoMap
  22460. this.aoMapIntensity = source.aoMapIntensity
  22461. this.emissive.copy(source.emissive)
  22462. this.emissiveMap = source.emissiveMap
  22463. this.emissiveIntensity = source.emissiveIntensity
  22464. this.bumpMap = source.bumpMap
  22465. this.bumpScale = source.bumpScale
  22466. this.normalMap = source.normalMap
  22467. this.normalMapType = source.normalMapType
  22468. this.normalScale.copy(source.normalScale)
  22469. this.displacementMap = source.displacementMap
  22470. this.displacementScale = source.displacementScale
  22471. this.displacementBias = source.displacementBias
  22472. this.roughnessMap = source.roughnessMap
  22473. this.metalnessMap = source.metalnessMap
  22474. this.alphaMap = source.alphaMap
  22475. this.envMap = source.envMap
  22476. this.envMapIntensity = source.envMapIntensity
  22477. this.wireframe = source.wireframe
  22478. this.wireframeLinewidth = source.wireframeLinewidth
  22479. this.wireframeLinecap = source.wireframeLinecap
  22480. this.wireframeLinejoin = source.wireframeLinejoin
  22481. this.flatShading = source.flatShading
  22482. this.fog = source.fog
  22483. return this
  22484. }
  22485. }
  22486. class MeshPhysicalMaterial extends MeshStandardMaterial {
  22487. constructor(parameters) {
  22488. super()
  22489. this.isMeshPhysicalMaterial = true
  22490. this.defines = {
  22491. STANDARD: '',
  22492. PHYSICAL: ''
  22493. }
  22494. this.type = 'MeshPhysicalMaterial'
  22495. this.clearcoatMap = null
  22496. this.clearcoatRoughness = 0.0
  22497. this.clearcoatRoughnessMap = null
  22498. this.clearcoatNormalScale = new Vector2(1, 1)
  22499. this.clearcoatNormalMap = null
  22500. this.ior = 1.5
  22501. Object.defineProperty(this, 'reflectivity', {
  22502. get: function() {
  22503. return clamp((2.5 * (this.ior - 1)) / (this.ior + 1), 0, 1)
  22504. },
  22505. set: function(reflectivity) {
  22506. this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity)
  22507. }
  22508. })
  22509. this.iridescenceMap = null
  22510. this.iridescenceIOR = 1.3
  22511. this.iridescenceThicknessRange = [100, 400]
  22512. this.iridescenceThicknessMap = null
  22513. this.sheenColor = new Color(0x000000)
  22514. this.sheenColorMap = null
  22515. this.sheenRoughness = 1.0
  22516. this.sheenRoughnessMap = null
  22517. this.transmissionMap = null
  22518. this.thickness = 0
  22519. this.thicknessMap = null
  22520. this.attenuationDistance = 0.0
  22521. this.attenuationColor = new Color(1, 1, 1)
  22522. this.specularIntensity = 1.0
  22523. this.specularIntensityMap = null
  22524. this.specularColor = new Color(1, 1, 1)
  22525. this.specularColorMap = null
  22526. this._sheen = 0.0
  22527. this._clearcoat = 0
  22528. this._iridescence = 0
  22529. this._transmission = 0
  22530. this.setValues(parameters)
  22531. }
  22532. get sheen() {
  22533. return this._sheen
  22534. }
  22535. set sheen(value) {
  22536. if (this._sheen > 0 !== value > 0) {
  22537. this.version++
  22538. }
  22539. this._sheen = value
  22540. }
  22541. get clearcoat() {
  22542. return this._clearcoat
  22543. }
  22544. set clearcoat(value) {
  22545. if (this._clearcoat > 0 !== value > 0) {
  22546. this.version++
  22547. }
  22548. this._clearcoat = value
  22549. }
  22550. get iridescence() {
  22551. return this._iridescence
  22552. }
  22553. set iridescence(value) {
  22554. if (this._iridescence > 0 !== value > 0) {
  22555. this.version++
  22556. }
  22557. this._iridescence = value
  22558. }
  22559. get transmission() {
  22560. return this._transmission
  22561. }
  22562. set transmission(value) {
  22563. if (this._transmission > 0 !== value > 0) {
  22564. this.version++
  22565. }
  22566. this._transmission = value
  22567. }
  22568. copy(source) {
  22569. super.copy(source)
  22570. this.defines = {
  22571. STANDARD: '',
  22572. PHYSICAL: ''
  22573. }
  22574. this.clearcoat = source.clearcoat
  22575. this.clearcoatMap = source.clearcoatMap
  22576. this.clearcoatRoughness = source.clearcoatRoughness
  22577. this.clearcoatRoughnessMap = source.clearcoatRoughnessMap
  22578. this.clearcoatNormalMap = source.clearcoatNormalMap
  22579. this.clearcoatNormalScale.copy(source.clearcoatNormalScale)
  22580. this.ior = source.ior
  22581. this.iridescence = source.iridescence
  22582. this.iridescenceMap = source.iridescenceMap
  22583. this.iridescenceIOR = source.iridescenceIOR
  22584. this.iridescenceThicknessRange = [...source.iridescenceThicknessRange]
  22585. this.iridescenceThicknessMap = source.iridescenceThicknessMap
  22586. this.sheen = source.sheen
  22587. this.sheenColor.copy(source.sheenColor)
  22588. this.sheenColorMap = source.sheenColorMap
  22589. this.sheenRoughness = source.sheenRoughness
  22590. this.sheenRoughnessMap = source.sheenRoughnessMap
  22591. this.transmission = source.transmission
  22592. this.transmissionMap = source.transmissionMap
  22593. this.thickness = source.thickness
  22594. this.thicknessMap = source.thicknessMap
  22595. this.attenuationDistance = source.attenuationDistance
  22596. this.attenuationColor.copy(source.attenuationColor)
  22597. this.specularIntensity = source.specularIntensity
  22598. this.specularIntensityMap = source.specularIntensityMap
  22599. this.specularColor.copy(source.specularColor)
  22600. this.specularColorMap = source.specularColorMap
  22601. return this
  22602. }
  22603. }
  22604. class MeshPhongMaterial extends Material {
  22605. constructor(parameters) {
  22606. super()
  22607. this.isMeshPhongMaterial = true
  22608. this.type = 'MeshPhongMaterial'
  22609. this.color = new Color(0xffffff) // diffuse
  22610. this.specular = new Color(0x111111)
  22611. this.shininess = 30
  22612. this.map = null
  22613. this.lightMap = null
  22614. this.lightMapIntensity = 1.0
  22615. this.aoMap = null
  22616. this.aoMapIntensity = 1.0
  22617. this.emissive = new Color(0x000000)
  22618. this.emissiveIntensity = 1.0
  22619. this.emissiveMap = null
  22620. this.bumpMap = null
  22621. this.bumpScale = 1
  22622. this.normalMap = null
  22623. this.normalMapType = TangentSpaceNormalMap
  22624. this.normalScale = new Vector2(1, 1)
  22625. this.displacementMap = null
  22626. this.displacementScale = 1
  22627. this.displacementBias = 0
  22628. this.specularMap = null
  22629. this.alphaMap = null
  22630. this.envMap = null
  22631. this.combine = MultiplyOperation
  22632. this.reflectivity = 1
  22633. this.refractionRatio = 0.98
  22634. this.wireframe = false
  22635. this.wireframeLinewidth = 1
  22636. this.wireframeLinecap = 'round'
  22637. this.wireframeLinejoin = 'round'
  22638. this.flatShading = false
  22639. this.fog = true
  22640. this.setValues(parameters)
  22641. }
  22642. copy(source) {
  22643. super.copy(source)
  22644. this.color.copy(source.color)
  22645. this.specular.copy(source.specular)
  22646. this.shininess = source.shininess
  22647. this.map = source.map
  22648. this.lightMap = source.lightMap
  22649. this.lightMapIntensity = source.lightMapIntensity
  22650. this.aoMap = source.aoMap
  22651. this.aoMapIntensity = source.aoMapIntensity
  22652. this.emissive.copy(source.emissive)
  22653. this.emissiveMap = source.emissiveMap
  22654. this.emissiveIntensity = source.emissiveIntensity
  22655. this.bumpMap = source.bumpMap
  22656. this.bumpScale = source.bumpScale
  22657. this.normalMap = source.normalMap
  22658. this.normalMapType = source.normalMapType
  22659. this.normalScale.copy(source.normalScale)
  22660. this.displacementMap = source.displacementMap
  22661. this.displacementScale = source.displacementScale
  22662. this.displacementBias = source.displacementBias
  22663. this.specularMap = source.specularMap
  22664. this.alphaMap = source.alphaMap
  22665. this.envMap = source.envMap
  22666. this.combine = source.combine
  22667. this.reflectivity = source.reflectivity
  22668. this.refractionRatio = source.refractionRatio
  22669. this.wireframe = source.wireframe
  22670. this.wireframeLinewidth = source.wireframeLinewidth
  22671. this.wireframeLinecap = source.wireframeLinecap
  22672. this.wireframeLinejoin = source.wireframeLinejoin
  22673. this.flatShading = source.flatShading
  22674. this.fog = source.fog
  22675. return this
  22676. }
  22677. }
  22678. class MeshToonMaterial extends Material {
  22679. constructor(parameters) {
  22680. super()
  22681. this.isMeshToonMaterial = true
  22682. this.defines = { TOON: '' }
  22683. this.type = 'MeshToonMaterial'
  22684. this.color = new Color(0xffffff)
  22685. this.map = null
  22686. this.gradientMap = null
  22687. this.lightMap = null
  22688. this.lightMapIntensity = 1.0
  22689. this.aoMap = null
  22690. this.aoMapIntensity = 1.0
  22691. this.emissive = new Color(0x000000)
  22692. this.emissiveIntensity = 1.0
  22693. this.emissiveMap = null
  22694. this.bumpMap = null
  22695. this.bumpScale = 1
  22696. this.normalMap = null
  22697. this.normalMapType = TangentSpaceNormalMap
  22698. this.normalScale = new Vector2(1, 1)
  22699. this.displacementMap = null
  22700. this.displacementScale = 1
  22701. this.displacementBias = 0
  22702. this.alphaMap = null
  22703. this.wireframe = false
  22704. this.wireframeLinewidth = 1
  22705. this.wireframeLinecap = 'round'
  22706. this.wireframeLinejoin = 'round'
  22707. this.fog = true
  22708. this.setValues(parameters)
  22709. }
  22710. copy(source) {
  22711. super.copy(source)
  22712. this.color.copy(source.color)
  22713. this.map = source.map
  22714. this.gradientMap = source.gradientMap
  22715. this.lightMap = source.lightMap
  22716. this.lightMapIntensity = source.lightMapIntensity
  22717. this.aoMap = source.aoMap
  22718. this.aoMapIntensity = source.aoMapIntensity
  22719. this.emissive.copy(source.emissive)
  22720. this.emissiveMap = source.emissiveMap
  22721. this.emissiveIntensity = source.emissiveIntensity
  22722. this.bumpMap = source.bumpMap
  22723. this.bumpScale = source.bumpScale
  22724. this.normalMap = source.normalMap
  22725. this.normalMapType = source.normalMapType
  22726. this.normalScale.copy(source.normalScale)
  22727. this.displacementMap = source.displacementMap
  22728. this.displacementScale = source.displacementScale
  22729. this.displacementBias = source.displacementBias
  22730. this.alphaMap = source.alphaMap
  22731. this.wireframe = source.wireframe
  22732. this.wireframeLinewidth = source.wireframeLinewidth
  22733. this.wireframeLinecap = source.wireframeLinecap
  22734. this.wireframeLinejoin = source.wireframeLinejoin
  22735. this.fog = source.fog
  22736. return this
  22737. }
  22738. }
  22739. class MeshNormalMaterial extends Material {
  22740. constructor(parameters) {
  22741. super()
  22742. this.isMeshNormalMaterial = true
  22743. this.type = 'MeshNormalMaterial'
  22744. this.bumpMap = null
  22745. this.bumpScale = 1
  22746. this.normalMap = null
  22747. this.normalMapType = TangentSpaceNormalMap
  22748. this.normalScale = new Vector2(1, 1)
  22749. this.displacementMap = null
  22750. this.displacementScale = 1
  22751. this.displacementBias = 0
  22752. this.wireframe = false
  22753. this.wireframeLinewidth = 1
  22754. this.flatShading = false
  22755. this.setValues(parameters)
  22756. }
  22757. copy(source) {
  22758. super.copy(source)
  22759. this.bumpMap = source.bumpMap
  22760. this.bumpScale = source.bumpScale
  22761. this.normalMap = source.normalMap
  22762. this.normalMapType = source.normalMapType
  22763. this.normalScale.copy(source.normalScale)
  22764. this.displacementMap = source.displacementMap
  22765. this.displacementScale = source.displacementScale
  22766. this.displacementBias = source.displacementBias
  22767. this.wireframe = source.wireframe
  22768. this.wireframeLinewidth = source.wireframeLinewidth
  22769. this.flatShading = source.flatShading
  22770. return this
  22771. }
  22772. }
  22773. class MeshLambertMaterial extends Material {
  22774. constructor(parameters) {
  22775. super()
  22776. this.isMeshLambertMaterial = true
  22777. this.type = 'MeshLambertMaterial'
  22778. this.color = new Color(0xffffff) // diffuse
  22779. this.map = null
  22780. this.lightMap = null
  22781. this.lightMapIntensity = 1.0
  22782. this.aoMap = null
  22783. this.aoMapIntensity = 1.0
  22784. this.emissive = new Color(0x000000)
  22785. this.emissiveIntensity = 1.0
  22786. this.emissiveMap = null
  22787. this.specularMap = null
  22788. this.alphaMap = null
  22789. this.envMap = null
  22790. this.combine = MultiplyOperation
  22791. this.reflectivity = 1
  22792. this.refractionRatio = 0.98
  22793. this.wireframe = false
  22794. this.wireframeLinewidth = 1
  22795. this.wireframeLinecap = 'round'
  22796. this.wireframeLinejoin = 'round'
  22797. this.fog = true
  22798. this.setValues(parameters)
  22799. }
  22800. copy(source) {
  22801. super.copy(source)
  22802. this.color.copy(source.color)
  22803. this.map = source.map
  22804. this.lightMap = source.lightMap
  22805. this.lightMapIntensity = source.lightMapIntensity
  22806. this.aoMap = source.aoMap
  22807. this.aoMapIntensity = source.aoMapIntensity
  22808. this.emissive.copy(source.emissive)
  22809. this.emissiveMap = source.emissiveMap
  22810. this.emissiveIntensity = source.emissiveIntensity
  22811. this.specularMap = source.specularMap
  22812. this.alphaMap = source.alphaMap
  22813. this.envMap = source.envMap
  22814. this.combine = source.combine
  22815. this.reflectivity = source.reflectivity
  22816. this.refractionRatio = source.refractionRatio
  22817. this.wireframe = source.wireframe
  22818. this.wireframeLinewidth = source.wireframeLinewidth
  22819. this.wireframeLinecap = source.wireframeLinecap
  22820. this.wireframeLinejoin = source.wireframeLinejoin
  22821. this.fog = source.fog
  22822. return this
  22823. }
  22824. }
  22825. class MeshMatcapMaterial extends Material {
  22826. constructor(parameters) {
  22827. super()
  22828. this.isMeshMatcapMaterial = true
  22829. this.defines = { MATCAP: '' }
  22830. this.type = 'MeshMatcapMaterial'
  22831. this.color = new Color(0xffffff) // diffuse
  22832. this.matcap = null
  22833. this.map = null
  22834. this.bumpMap = null
  22835. this.bumpScale = 1
  22836. this.normalMap = null
  22837. this.normalMapType = TangentSpaceNormalMap
  22838. this.normalScale = new Vector2(1, 1)
  22839. this.displacementMap = null
  22840. this.displacementScale = 1
  22841. this.displacementBias = 0
  22842. this.alphaMap = null
  22843. this.flatShading = false
  22844. this.fog = true
  22845. this.setValues(parameters)
  22846. }
  22847. copy(source) {
  22848. super.copy(source)
  22849. this.defines = { MATCAP: '' }
  22850. this.color.copy(source.color)
  22851. this.matcap = source.matcap
  22852. this.map = source.map
  22853. this.bumpMap = source.bumpMap
  22854. this.bumpScale = source.bumpScale
  22855. this.normalMap = source.normalMap
  22856. this.normalMapType = source.normalMapType
  22857. this.normalScale.copy(source.normalScale)
  22858. this.displacementMap = source.displacementMap
  22859. this.displacementScale = source.displacementScale
  22860. this.displacementBias = source.displacementBias
  22861. this.alphaMap = source.alphaMap
  22862. this.flatShading = source.flatShading
  22863. this.fog = source.fog
  22864. return this
  22865. }
  22866. }
  22867. class LineDashedMaterial extends LineBasicMaterial {
  22868. constructor(parameters) {
  22869. super()
  22870. this.isLineDashedMaterial = true
  22871. this.type = 'LineDashedMaterial'
  22872. this.scale = 1
  22873. this.dashSize = 3
  22874. this.gapSize = 1
  22875. this.setValues(parameters)
  22876. }
  22877. copy(source) {
  22878. super.copy(source)
  22879. this.scale = source.scale
  22880. this.dashSize = source.dashSize
  22881. this.gapSize = source.gapSize
  22882. return this
  22883. }
  22884. }
  22885. const materialLib = {
  22886. ShadowMaterial,
  22887. SpriteMaterial,
  22888. RawShaderMaterial,
  22889. ShaderMaterial,
  22890. PointsMaterial,
  22891. MeshPhysicalMaterial,
  22892. MeshStandardMaterial,
  22893. MeshPhongMaterial,
  22894. MeshToonMaterial,
  22895. MeshNormalMaterial,
  22896. MeshLambertMaterial,
  22897. MeshDepthMaterial,
  22898. MeshDistanceMaterial,
  22899. MeshBasicMaterial,
  22900. MeshMatcapMaterial,
  22901. LineDashedMaterial,
  22902. LineBasicMaterial,
  22903. Material
  22904. }
  22905. Material.fromType = function(type) {
  22906. return new materialLib[type]()
  22907. }
  22908. const AnimationUtils = {
  22909. // same as Array.prototype.slice, but also works on typed arrays
  22910. arraySlice: function(array, from, to) {
  22911. if (AnimationUtils.isTypedArray(array)) {
  22912. // in ios9 array.subarray(from, undefined) will return empty array
  22913. // but array.subarray(from) or array.subarray(from, len) is correct
  22914. return new array.constructor(array.subarray(from, to !== undefined ? to : array.length))
  22915. }
  22916. return array.slice(from, to)
  22917. },
  22918. // converts an array to a specific type
  22919. convertArray: function(array, type, forceClone) {
  22920. if (
  22921. !array || // let 'undefined' and 'null' pass
  22922. (!forceClone && array.constructor === type)
  22923. )
  22924. return array
  22925. if (typeof type.BYTES_PER_ELEMENT === 'number') {
  22926. return new type(array) // create typed array
  22927. }
  22928. return Array.prototype.slice.call(array) // create Array
  22929. },
  22930. isTypedArray: function(object) {
  22931. return ArrayBuffer.isView(object) && !(object instanceof DataView)
  22932. },
  22933. // returns an array by which times and values can be sorted
  22934. getKeyframeOrder: function(times) {
  22935. function compareTime(i, j) {
  22936. return times[i] - times[j]
  22937. }
  22938. const n = times.length
  22939. const result = new Array(n)
  22940. for (let i = 0; i !== n; ++i) result[i] = i
  22941. result.sort(compareTime)
  22942. return result
  22943. },
  22944. // uses the array previously returned by 'getKeyframeOrder' to sort data
  22945. sortedArray: function(values, stride, order) {
  22946. const nValues = values.length
  22947. const result = new values.constructor(nValues)
  22948. for (let i = 0, dstOffset = 0; dstOffset !== nValues; ++i) {
  22949. const srcOffset = order[i] * stride
  22950. for (let j = 0; j !== stride; ++j) {
  22951. result[dstOffset++] = values[srcOffset + j]
  22952. }
  22953. }
  22954. return result
  22955. },
  22956. // function for parsing AOS keyframe formats
  22957. flattenJSON: function(jsonKeys, times, values, valuePropertyName) {
  22958. let i = 1,
  22959. key = jsonKeys[0]
  22960. while (key !== undefined && key[valuePropertyName] === undefined) {
  22961. key = jsonKeys[i++]
  22962. }
  22963. if (key === undefined) return // no data
  22964. let value = key[valuePropertyName]
  22965. if (value === undefined) return // no data
  22966. if (Array.isArray(value)) {
  22967. do {
  22968. value = key[valuePropertyName]
  22969. if (value !== undefined) {
  22970. times.push(key.time)
  22971. values.push.apply(values, value) // push all elements
  22972. }
  22973. key = jsonKeys[i++]
  22974. } while (key !== undefined)
  22975. } else if (value.toArray !== undefined) {
  22976. // ...assume THREE.Math-ish
  22977. do {
  22978. value = key[valuePropertyName]
  22979. if (value !== undefined) {
  22980. times.push(key.time)
  22981. value.toArray(values, values.length)
  22982. }
  22983. key = jsonKeys[i++]
  22984. } while (key !== undefined)
  22985. } else {
  22986. // otherwise push as-is
  22987. do {
  22988. value = key[valuePropertyName]
  22989. if (value !== undefined) {
  22990. times.push(key.time)
  22991. values.push(value)
  22992. }
  22993. key = jsonKeys[i++]
  22994. } while (key !== undefined)
  22995. }
  22996. },
  22997. subclip: function(sourceClip, name, startFrame, endFrame, fps = 30) {
  22998. const clip = sourceClip.clone()
  22999. clip.name = name
  23000. const tracks = []
  23001. for (let i = 0; i < clip.tracks.length; ++i) {
  23002. const track = clip.tracks[i]
  23003. const valueSize = track.getValueSize()
  23004. const times = []
  23005. const values = []
  23006. for (let j = 0; j < track.times.length; ++j) {
  23007. const frame = track.times[j] * fps
  23008. if (frame < startFrame || frame >= endFrame) continue
  23009. times.push(track.times[j])
  23010. for (let k = 0; k < valueSize; ++k) {
  23011. values.push(track.values[j * valueSize + k])
  23012. }
  23013. }
  23014. if (times.length === 0) continue
  23015. track.times = AnimationUtils.convertArray(times, track.times.constructor)
  23016. track.values = AnimationUtils.convertArray(values, track.values.constructor)
  23017. tracks.push(track)
  23018. }
  23019. clip.tracks = tracks
  23020. // find minimum .times value across all tracks in the trimmed clip
  23021. let minStartTime = Infinity
  23022. for (let i = 0; i < clip.tracks.length; ++i) {
  23023. if (minStartTime > clip.tracks[i].times[0]) {
  23024. minStartTime = clip.tracks[i].times[0]
  23025. }
  23026. }
  23027. // shift all tracks such that clip begins at t=0
  23028. for (let i = 0; i < clip.tracks.length; ++i) {
  23029. clip.tracks[i].shift(-1 * minStartTime)
  23030. }
  23031. clip.resetDuration()
  23032. return clip
  23033. },
  23034. makeClipAdditive: function(targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30) {
  23035. if (fps <= 0) fps = 30
  23036. const numTracks = referenceClip.tracks.length
  23037. const referenceTime = referenceFrame / fps
  23038. // Make each track's values relative to the values at the reference frame
  23039. for (let i = 0; i < numTracks; ++i) {
  23040. const referenceTrack = referenceClip.tracks[i]
  23041. const referenceTrackType = referenceTrack.ValueTypeName
  23042. // Skip this track if it's non-numeric
  23043. if (referenceTrackType === 'bool' || referenceTrackType === 'string') continue
  23044. // Find the track in the target clip whose name and type matches the reference track
  23045. const targetTrack = targetClip.tracks.find(function(track) {
  23046. return track.name === referenceTrack.name && track.ValueTypeName === referenceTrackType
  23047. })
  23048. if (targetTrack === undefined) continue
  23049. let referenceOffset = 0
  23050. const referenceValueSize = referenceTrack.getValueSize()
  23051. if (referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
  23052. referenceOffset = referenceValueSize / 3
  23053. }
  23054. let targetOffset = 0
  23055. const targetValueSize = targetTrack.getValueSize()
  23056. if (targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
  23057. targetOffset = targetValueSize / 3
  23058. }
  23059. const lastIndex = referenceTrack.times.length - 1
  23060. let referenceValue
  23061. // Find the value to subtract out of the track
  23062. if (referenceTime <= referenceTrack.times[0]) {
  23063. // Reference frame is earlier than the first keyframe, so just use the first keyframe
  23064. const startIndex = referenceOffset
  23065. const endIndex = referenceValueSize - referenceOffset
  23066. referenceValue = AnimationUtils.arraySlice(referenceTrack.values, startIndex, endIndex)
  23067. } else if (referenceTime >= referenceTrack.times[lastIndex]) {
  23068. // Reference frame is after the last keyframe, so just use the last keyframe
  23069. const startIndex = lastIndex * referenceValueSize + referenceOffset
  23070. const endIndex = startIndex + referenceValueSize - referenceOffset
  23071. referenceValue = AnimationUtils.arraySlice(referenceTrack.values, startIndex, endIndex)
  23072. } else {
  23073. // Interpolate to the reference value
  23074. const interpolant = referenceTrack.createInterpolant()
  23075. const startIndex = referenceOffset
  23076. const endIndex = referenceValueSize - referenceOffset
  23077. interpolant.evaluate(referenceTime)
  23078. referenceValue = AnimationUtils.arraySlice(interpolant.resultBuffer, startIndex, endIndex)
  23079. }
  23080. // Conjugate the quaternion
  23081. if (referenceTrackType === 'quaternion') {
  23082. const referenceQuat = new Quaternion()
  23083. .fromArray(referenceValue)
  23084. .normalize()
  23085. .conjugate()
  23086. referenceQuat.toArray(referenceValue)
  23087. }
  23088. // Subtract the reference value from all of the track values
  23089. const numTimes = targetTrack.times.length
  23090. for (let j = 0; j < numTimes; ++j) {
  23091. const valueStart = j * targetValueSize + targetOffset
  23092. if (referenceTrackType === 'quaternion') {
  23093. // Multiply the conjugate for quaternion track types
  23094. Quaternion.multiplyQuaternionsFlat(targetTrack.values, valueStart, referenceValue, 0, targetTrack.values, valueStart)
  23095. } else {
  23096. const valueEnd = targetValueSize - targetOffset * 2
  23097. // Subtract each value for all other numeric track types
  23098. for (let k = 0; k < valueEnd; ++k) {
  23099. targetTrack.values[valueStart + k] -= referenceValue[k]
  23100. }
  23101. }
  23102. }
  23103. }
  23104. targetClip.blendMode = AdditiveAnimationBlendMode
  23105. return targetClip
  23106. }
  23107. }
  23108. /**
  23109. * Abstract base class of interpolants over parametric samples.
  23110. *
  23111. * The parameter domain is one dimensional, typically the time or a path
  23112. * along a curve defined by the data.
  23113. *
  23114. * The sample values can have any dimensionality and derived classes may
  23115. * apply special interpretations to the data.
  23116. *
  23117. * This class provides the interval seek in a Template Method, deferring
  23118. * the actual interpolation to derived classes.
  23119. *
  23120. * Time complexity is O(1) for linear access crossing at most two points
  23121. * and O(log N) for random access, where N is the number of positions.
  23122. *
  23123. * References:
  23124. *
  23125. * http://www.oodesign.com/template-method-pattern.html
  23126. *
  23127. */
  23128. class Interpolant {
  23129. constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  23130. this.parameterPositions = parameterPositions
  23131. this._cachedIndex = 0
  23132. this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor(sampleSize)
  23133. this.sampleValues = sampleValues
  23134. this.valueSize = sampleSize
  23135. this.settings = null
  23136. this.DefaultSettings_ = {}
  23137. }
  23138. evaluate(t) {
  23139. const pp = this.parameterPositions
  23140. let i1 = this._cachedIndex,
  23141. t1 = pp[i1],
  23142. t0 = pp[i1 - 1]
  23143. validate_interval: {
  23144. seek: {
  23145. let right
  23146. linear_scan: {
  23147. //- See http://jsperf.com/comparison-to-undefined/3
  23148. //- slower code:
  23149. //-
  23150. //- if ( t >= t1 || t1 === undefined ) {
  23151. forward_scan: if (!(t < t1)) {
  23152. for (let giveUpAt = i1 + 2; ; ) {
  23153. if (t1 === undefined) {
  23154. if (t < t0) break forward_scan
  23155. // after end
  23156. i1 = pp.length
  23157. this._cachedIndex = i1
  23158. return this.copySampleValue_(i1 - 1)
  23159. }
  23160. if (i1 === giveUpAt) break // this loop
  23161. t0 = t1
  23162. t1 = pp[++i1]
  23163. if (t < t1) {
  23164. // we have arrived at the sought interval
  23165. break seek
  23166. }
  23167. }
  23168. // prepare binary search on the right side of the index
  23169. right = pp.length
  23170. break linear_scan
  23171. }
  23172. //- slower code:
  23173. //- if ( t < t0 || t0 === undefined ) {
  23174. if (!(t >= t0)) {
  23175. // looping?
  23176. const t1global = pp[1]
  23177. if (t < t1global) {
  23178. i1 = 2 // + 1, using the scan for the details
  23179. t0 = t1global
  23180. }
  23181. // linear reverse scan
  23182. for (let giveUpAt = i1 - 2; ; ) {
  23183. if (t0 === undefined) {
  23184. // before start
  23185. this._cachedIndex = 0
  23186. return this.copySampleValue_(0)
  23187. }
  23188. if (i1 === giveUpAt) break // this loop
  23189. t1 = t0
  23190. t0 = pp[--i1 - 1]
  23191. if (t >= t0) {
  23192. // we have arrived at the sought interval
  23193. break seek
  23194. }
  23195. }
  23196. // prepare binary search on the left side of the index
  23197. right = i1
  23198. i1 = 0
  23199. break linear_scan
  23200. }
  23201. // the interval is valid
  23202. break validate_interval
  23203. } // linear scan
  23204. // binary search
  23205. while (i1 < right) {
  23206. const mid = (i1 + right) >>> 1
  23207. if (t < pp[mid]) {
  23208. right = mid
  23209. } else {
  23210. i1 = mid + 1
  23211. }
  23212. }
  23213. t1 = pp[i1]
  23214. t0 = pp[i1 - 1]
  23215. // check boundary cases, again
  23216. if (t0 === undefined) {
  23217. this._cachedIndex = 0
  23218. return this.copySampleValue_(0)
  23219. }
  23220. if (t1 === undefined) {
  23221. i1 = pp.length
  23222. this._cachedIndex = i1
  23223. return this.copySampleValue_(i1 - 1)
  23224. }
  23225. } // seek
  23226. this._cachedIndex = i1
  23227. this.intervalChanged_(i1, t0, t1)
  23228. } // validate_interval
  23229. return this.interpolate_(i1, t0, t, t1)
  23230. }
  23231. getSettings_() {
  23232. return this.settings || this.DefaultSettings_
  23233. }
  23234. copySampleValue_(index) {
  23235. // copies a sample value to the result buffer
  23236. const result = this.resultBuffer,
  23237. values = this.sampleValues,
  23238. stride = this.valueSize,
  23239. offset = index * stride
  23240. for (let i = 0; i !== stride; ++i) {
  23241. result[i] = values[offset + i]
  23242. }
  23243. return result
  23244. }
  23245. // Template methods for derived classes:
  23246. interpolate_(/* i1, t0, t, t1 */) {
  23247. throw new Error('call to abstract method')
  23248. // implementations shall return this.resultBuffer
  23249. }
  23250. intervalChanged_(/* i1, t0, t1 */) {
  23251. // empty
  23252. }
  23253. }
  23254. /**
  23255. * Fast and simple cubic spline interpolant.
  23256. *
  23257. * It was derived from a Hermitian construction setting the first derivative
  23258. * at each sample position to the linear slope between neighboring positions
  23259. * over their parameter interval.
  23260. */
  23261. class CubicInterpolant extends Interpolant {
  23262. constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  23263. super(parameterPositions, sampleValues, sampleSize, resultBuffer)
  23264. this._weightPrev = -0
  23265. this._offsetPrev = -0
  23266. this._weightNext = -0
  23267. this._offsetNext = -0
  23268. this.DefaultSettings_ = {
  23269. endingStart: ZeroCurvatureEnding,
  23270. endingEnd: ZeroCurvatureEnding
  23271. }
  23272. }
  23273. intervalChanged_(i1, t0, t1) {
  23274. const pp = this.parameterPositions
  23275. let iPrev = i1 - 2,
  23276. iNext = i1 + 1,
  23277. tPrev = pp[iPrev],
  23278. tNext = pp[iNext]
  23279. if (tPrev === undefined) {
  23280. switch (this.getSettings_().endingStart) {
  23281. case ZeroSlopeEnding:
  23282. // f'(t0) = 0
  23283. iPrev = i1
  23284. tPrev = 2 * t0 - t1
  23285. break
  23286. case WrapAroundEnding:
  23287. // use the other end of the curve
  23288. iPrev = pp.length - 2
  23289. tPrev = t0 + pp[iPrev] - pp[iPrev + 1]
  23290. break
  23291. default:
  23292. // ZeroCurvatureEnding
  23293. // f''(t0) = 0 a.k.a. Natural Spline
  23294. iPrev = i1
  23295. tPrev = t1
  23296. }
  23297. }
  23298. if (tNext === undefined) {
  23299. switch (this.getSettings_().endingEnd) {
  23300. case ZeroSlopeEnding:
  23301. // f'(tN) = 0
  23302. iNext = i1
  23303. tNext = 2 * t1 - t0
  23304. break
  23305. case WrapAroundEnding:
  23306. // use the other end of the curve
  23307. iNext = 1
  23308. tNext = t1 + pp[1] - pp[0]
  23309. break
  23310. default:
  23311. // ZeroCurvatureEnding
  23312. // f''(tN) = 0, a.k.a. Natural Spline
  23313. iNext = i1 - 1
  23314. tNext = t0
  23315. }
  23316. }
  23317. const halfDt = (t1 - t0) * 0.5,
  23318. stride = this.valueSize
  23319. this._weightPrev = halfDt / (t0 - tPrev)
  23320. this._weightNext = halfDt / (tNext - t1)
  23321. this._offsetPrev = iPrev * stride
  23322. this._offsetNext = iNext * stride
  23323. }
  23324. interpolate_(i1, t0, t, t1) {
  23325. const result = this.resultBuffer,
  23326. values = this.sampleValues,
  23327. stride = this.valueSize,
  23328. o1 = i1 * stride,
  23329. o0 = o1 - stride,
  23330. oP = this._offsetPrev,
  23331. oN = this._offsetNext,
  23332. wP = this._weightPrev,
  23333. wN = this._weightNext,
  23334. p = (t - t0) / (t1 - t0),
  23335. pp = p * p,
  23336. ppp = pp * p
  23337. // evaluate polynomials
  23338. const sP = -wP * ppp + 2 * wP * pp - wP * p
  23339. const s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p + 1
  23340. const s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p
  23341. const sN = wN * ppp - wN * pp
  23342. // combine data linearly
  23343. for (let i = 0; i !== stride; ++i) {
  23344. result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i]
  23345. }
  23346. return result
  23347. }
  23348. }
  23349. class LinearInterpolant extends Interpolant {
  23350. constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  23351. super(parameterPositions, sampleValues, sampleSize, resultBuffer)
  23352. }
  23353. interpolate_(i1, t0, t, t1) {
  23354. const result = this.resultBuffer,
  23355. values = this.sampleValues,
  23356. stride = this.valueSize,
  23357. offset1 = i1 * stride,
  23358. offset0 = offset1 - stride,
  23359. weight1 = (t - t0) / (t1 - t0),
  23360. weight0 = 1 - weight1
  23361. for (let i = 0; i !== stride; ++i) {
  23362. result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1
  23363. }
  23364. return result
  23365. }
  23366. }
  23367. /**
  23368. *
  23369. * Interpolant that evaluates to the sample value at the position preceding
  23370. * the parameter.
  23371. */
  23372. class DiscreteInterpolant extends Interpolant {
  23373. constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  23374. super(parameterPositions, sampleValues, sampleSize, resultBuffer)
  23375. }
  23376. interpolate_(i1 /*, t0, t, t1 */) {
  23377. return this.copySampleValue_(i1 - 1)
  23378. }
  23379. }
  23380. class KeyframeTrack {
  23381. constructor(name, times, values, interpolation) {
  23382. if (name === undefined) throw new Error('THREE.KeyframeTrack: track name is undefined')
  23383. if (times === undefined || times.length === 0) throw new Error('THREE.KeyframeTrack: no keyframes in track named ' + name)
  23384. this.name = name
  23385. this.times = AnimationUtils.convertArray(times, this.TimeBufferType)
  23386. this.values = AnimationUtils.convertArray(values, this.ValueBufferType)
  23387. this.setInterpolation(interpolation || this.DefaultInterpolation)
  23388. }
  23389. // Serialization (in static context, because of constructor invocation
  23390. // and automatic invocation of .toJSON):
  23391. static toJSON(track) {
  23392. const trackType = track.constructor
  23393. let json
  23394. // derived classes can define a static toJSON method
  23395. if (trackType.toJSON !== this.toJSON) {
  23396. json = trackType.toJSON(track)
  23397. } else {
  23398. // by default, we assume the data can be serialized as-is
  23399. json = {
  23400. name: track.name,
  23401. times: AnimationUtils.convertArray(track.times, Array),
  23402. values: AnimationUtils.convertArray(track.values, Array)
  23403. }
  23404. const interpolation = track.getInterpolation()
  23405. if (interpolation !== track.DefaultInterpolation) {
  23406. json.interpolation = interpolation
  23407. }
  23408. }
  23409. json.type = track.ValueTypeName // mandatory
  23410. return json
  23411. }
  23412. InterpolantFactoryMethodDiscrete(result) {
  23413. return new DiscreteInterpolant(this.times, this.values, this.getValueSize(), result)
  23414. }
  23415. InterpolantFactoryMethodLinear(result) {
  23416. return new LinearInterpolant(this.times, this.values, this.getValueSize(), result)
  23417. }
  23418. InterpolantFactoryMethodSmooth(result) {
  23419. return new CubicInterpolant(this.times, this.values, this.getValueSize(), result)
  23420. }
  23421. setInterpolation(interpolation) {
  23422. let factoryMethod
  23423. switch (interpolation) {
  23424. case InterpolateDiscrete:
  23425. factoryMethod = this.InterpolantFactoryMethodDiscrete
  23426. break
  23427. case InterpolateLinear:
  23428. factoryMethod = this.InterpolantFactoryMethodLinear
  23429. break
  23430. case InterpolateSmooth:
  23431. factoryMethod = this.InterpolantFactoryMethodSmooth
  23432. break
  23433. }
  23434. if (factoryMethod === undefined) {
  23435. const message = 'unsupported interpolation for ' + this.ValueTypeName + ' keyframe track named ' + this.name
  23436. if (this.createInterpolant === undefined) {
  23437. // fall back to default, unless the default itself is messed up
  23438. if (interpolation !== this.DefaultInterpolation) {
  23439. this.setInterpolation(this.DefaultInterpolation)
  23440. } else {
  23441. throw new Error(message) // fatal, in this case
  23442. }
  23443. }
  23444. console.warn('THREE.KeyframeTrack:', message)
  23445. return this
  23446. }
  23447. this.createInterpolant = factoryMethod
  23448. return this
  23449. }
  23450. getInterpolation() {
  23451. switch (this.createInterpolant) {
  23452. case this.InterpolantFactoryMethodDiscrete:
  23453. return InterpolateDiscrete
  23454. case this.InterpolantFactoryMethodLinear:
  23455. return InterpolateLinear
  23456. case this.InterpolantFactoryMethodSmooth:
  23457. return InterpolateSmooth
  23458. }
  23459. }
  23460. getValueSize() {
  23461. return this.values.length / this.times.length
  23462. }
  23463. // move all keyframes either forwards or backwards in time
  23464. shift(timeOffset) {
  23465. if (timeOffset !== 0.0) {
  23466. const times = this.times
  23467. for (let i = 0, n = times.length; i !== n; ++i) {
  23468. times[i] += timeOffset
  23469. }
  23470. }
  23471. return this
  23472. }
  23473. // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
  23474. scale(timeScale) {
  23475. if (timeScale !== 1.0) {
  23476. const times = this.times
  23477. for (let i = 0, n = times.length; i !== n; ++i) {
  23478. times[i] *= timeScale
  23479. }
  23480. }
  23481. return this
  23482. }
  23483. // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
  23484. // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
  23485. trim(startTime, endTime) {
  23486. const times = this.times,
  23487. nKeys = times.length
  23488. let from = 0,
  23489. to = nKeys - 1
  23490. while (from !== nKeys && times[from] < startTime) {
  23491. ++from
  23492. }
  23493. while (to !== -1 && times[to] > endTime) {
  23494. --to
  23495. }
  23496. ++to // inclusive -> exclusive bound
  23497. if (from !== 0 || to !== nKeys) {
  23498. // empty tracks are forbidden, so keep at least one keyframe
  23499. if (from >= to) {
  23500. to = Math.max(to, 1)
  23501. from = to - 1
  23502. }
  23503. const stride = this.getValueSize()
  23504. this.times = AnimationUtils.arraySlice(times, from, to)
  23505. this.values = AnimationUtils.arraySlice(this.values, from * stride, to * stride)
  23506. }
  23507. return this
  23508. }
  23509. // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
  23510. validate() {
  23511. let valid = true
  23512. const valueSize = this.getValueSize()
  23513. if (valueSize - Math.floor(valueSize) !== 0) {
  23514. console.error('THREE.KeyframeTrack: Invalid value size in track.', this)
  23515. valid = false
  23516. }
  23517. const times = this.times,
  23518. values = this.values,
  23519. nKeys = times.length
  23520. if (nKeys === 0) {
  23521. console.error('THREE.KeyframeTrack: Track is empty.', this)
  23522. valid = false
  23523. }
  23524. let prevTime = null
  23525. for (let i = 0; i !== nKeys; i++) {
  23526. const currTime = times[i]
  23527. if (typeof currTime === 'number' && isNaN(currTime)) {
  23528. console.error('THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime)
  23529. valid = false
  23530. break
  23531. }
  23532. if (prevTime !== null && prevTime > currTime) {
  23533. console.error('THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime)
  23534. valid = false
  23535. break
  23536. }
  23537. prevTime = currTime
  23538. }
  23539. if (values !== undefined) {
  23540. if (AnimationUtils.isTypedArray(values)) {
  23541. for (let i = 0, n = values.length; i !== n; ++i) {
  23542. const value = values[i]
  23543. if (isNaN(value)) {
  23544. console.error('THREE.KeyframeTrack: Value is not a valid number.', this, i, value)
  23545. valid = false
  23546. break
  23547. }
  23548. }
  23549. }
  23550. }
  23551. return valid
  23552. }
  23553. // removes equivalent sequential keys as common in morph target sequences
  23554. // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
  23555. optimize() {
  23556. // times or values may be shared with other tracks, so overwriting is unsafe
  23557. const times = AnimationUtils.arraySlice(this.times),
  23558. values = AnimationUtils.arraySlice(this.values),
  23559. stride = this.getValueSize(),
  23560. smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
  23561. lastIndex = times.length - 1
  23562. let writeIndex = 1
  23563. for (let i = 1; i < lastIndex; ++i) {
  23564. let keep = false
  23565. const time = times[i]
  23566. const timeNext = times[i + 1]
  23567. // remove adjacent keyframes scheduled at the same time
  23568. if (time !== timeNext && (i !== 1 || time !== times[0])) {
  23569. if (!smoothInterpolation) {
  23570. // remove unnecessary keyframes same as their neighbors
  23571. const offset = i * stride,
  23572. offsetP = offset - stride,
  23573. offsetN = offset + stride
  23574. for (let j = 0; j !== stride; ++j) {
  23575. const value = values[offset + j]
  23576. if (value !== values[offsetP + j] || value !== values[offsetN + j]) {
  23577. keep = true
  23578. break
  23579. }
  23580. }
  23581. } else {
  23582. keep = true
  23583. }
  23584. }
  23585. // in-place compaction
  23586. if (keep) {
  23587. if (i !== writeIndex) {
  23588. times[writeIndex] = times[i]
  23589. const readOffset = i * stride,
  23590. writeOffset = writeIndex * stride
  23591. for (let j = 0; j !== stride; ++j) {
  23592. values[writeOffset + j] = values[readOffset + j]
  23593. }
  23594. }
  23595. ++writeIndex
  23596. }
  23597. }
  23598. // flush last keyframe (compaction looks ahead)
  23599. if (lastIndex > 0) {
  23600. times[writeIndex] = times[lastIndex]
  23601. for (let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++j) {
  23602. values[writeOffset + j] = values[readOffset + j]
  23603. }
  23604. ++writeIndex
  23605. }
  23606. if (writeIndex !== times.length) {
  23607. this.times = AnimationUtils.arraySlice(times, 0, writeIndex)
  23608. this.values = AnimationUtils.arraySlice(values, 0, writeIndex * stride)
  23609. } else {
  23610. this.times = times
  23611. this.values = values
  23612. }
  23613. return this
  23614. }
  23615. clone() {
  23616. const times = AnimationUtils.arraySlice(this.times, 0)
  23617. const values = AnimationUtils.arraySlice(this.values, 0)
  23618. const TypedKeyframeTrack = this.constructor
  23619. const track = new TypedKeyframeTrack(this.name, times, values)
  23620. // Interpolant argument to constructor is not saved, so copy the factory method directly.
  23621. track.createInterpolant = this.createInterpolant
  23622. return track
  23623. }
  23624. }
  23625. KeyframeTrack.prototype.TimeBufferType = Float32Array
  23626. KeyframeTrack.prototype.ValueBufferType = Float32Array
  23627. KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear
  23628. /**
  23629. * A Track of Boolean keyframe values.
  23630. */
  23631. class BooleanKeyframeTrack extends KeyframeTrack {}
  23632. BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'
  23633. BooleanKeyframeTrack.prototype.ValueBufferType = Array
  23634. BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete
  23635. BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined
  23636. BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined
  23637. /**
  23638. * A Track of keyframe values that represent color.
  23639. */
  23640. class ColorKeyframeTrack extends KeyframeTrack {}
  23641. ColorKeyframeTrack.prototype.ValueTypeName = 'color'
  23642. /**
  23643. * A Track of numeric keyframe values.
  23644. */
  23645. class NumberKeyframeTrack extends KeyframeTrack {}
  23646. NumberKeyframeTrack.prototype.ValueTypeName = 'number'
  23647. /**
  23648. * Spherical linear unit quaternion interpolant.
  23649. */
  23650. class QuaternionLinearInterpolant extends Interpolant {
  23651. constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
  23652. super(parameterPositions, sampleValues, sampleSize, resultBuffer)
  23653. }
  23654. interpolate_(i1, t0, t, t1) {
  23655. const result = this.resultBuffer,
  23656. values = this.sampleValues,
  23657. stride = this.valueSize,
  23658. alpha = (t - t0) / (t1 - t0)
  23659. let offset = i1 * stride
  23660. for (let end = offset + stride; offset !== end; offset += 4) {
  23661. Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha)
  23662. }
  23663. return result
  23664. }
  23665. }
  23666. /**
  23667. * A Track of quaternion keyframe values.
  23668. */
  23669. class QuaternionKeyframeTrack extends KeyframeTrack {
  23670. InterpolantFactoryMethodLinear(result) {
  23671. return new QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result)
  23672. }
  23673. }
  23674. QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'
  23675. // ValueBufferType is inherited
  23676. QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear
  23677. QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined
  23678. /**
  23679. * A Track that interpolates Strings
  23680. */
  23681. class StringKeyframeTrack extends KeyframeTrack {}
  23682. StringKeyframeTrack.prototype.ValueTypeName = 'string'
  23683. StringKeyframeTrack.prototype.ValueBufferType = Array
  23684. StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete
  23685. StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined
  23686. StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined
  23687. /**
  23688. * A Track of vectored keyframe values.
  23689. */
  23690. class VectorKeyframeTrack extends KeyframeTrack {}
  23691. VectorKeyframeTrack.prototype.ValueTypeName = 'vector'
  23692. class AnimationClip {
  23693. constructor(name, duration = -1, tracks, blendMode = NormalAnimationBlendMode) {
  23694. this.name = name
  23695. this.tracks = tracks
  23696. this.duration = duration
  23697. this.blendMode = blendMode
  23698. this.uuid = generateUUID()
  23699. // this means it should figure out its duration by scanning the tracks
  23700. if (this.duration < 0) {
  23701. this.resetDuration()
  23702. }
  23703. }
  23704. static parse(json) {
  23705. const tracks = [],
  23706. jsonTracks = json.tracks,
  23707. frameTime = 1.0 / (json.fps || 1.0)
  23708. for (let i = 0, n = jsonTracks.length; i !== n; ++i) {
  23709. tracks.push(parseKeyframeTrack(jsonTracks[i]).scale(frameTime))
  23710. }
  23711. const clip = new this(json.name, json.duration, tracks, json.blendMode)
  23712. clip.uuid = json.uuid
  23713. return clip
  23714. }
  23715. static toJSON(clip) {
  23716. const tracks = [],
  23717. clipTracks = clip.tracks
  23718. const json = {
  23719. name: clip.name,
  23720. duration: clip.duration,
  23721. tracks: tracks,
  23722. uuid: clip.uuid,
  23723. blendMode: clip.blendMode
  23724. }
  23725. for (let i = 0, n = clipTracks.length; i !== n; ++i) {
  23726. tracks.push(KeyframeTrack.toJSON(clipTracks[i]))
  23727. }
  23728. return json
  23729. }
  23730. static CreateFromMorphTargetSequence(name, morphTargetSequence, fps, noLoop) {
  23731. const numMorphTargets = morphTargetSequence.length
  23732. const tracks = []
  23733. for (let i = 0; i < numMorphTargets; i++) {
  23734. let times = []
  23735. let values = []
  23736. times.push((i + numMorphTargets - 1) % numMorphTargets, i, (i + 1) % numMorphTargets)
  23737. values.push(0, 1, 0)
  23738. const order = AnimationUtils.getKeyframeOrder(times)
  23739. times = AnimationUtils.sortedArray(times, 1, order)
  23740. values = AnimationUtils.sortedArray(values, 1, order)
  23741. // if there is a key at the first frame, duplicate it as the
  23742. // last frame as well for perfect loop.
  23743. if (!noLoop && times[0] === 0) {
  23744. times.push(numMorphTargets)
  23745. values.push(values[0])
  23746. }
  23747. tracks.push(new NumberKeyframeTrack('.morphTargetInfluences[' + morphTargetSequence[i].name + ']', times, values).scale(1.0 / fps))
  23748. }
  23749. return new this(name, -1, tracks)
  23750. }
  23751. static findByName(objectOrClipArray, name) {
  23752. let clipArray = objectOrClipArray
  23753. if (!Array.isArray(objectOrClipArray)) {
  23754. const o = objectOrClipArray
  23755. clipArray = (o.geometry && o.geometry.animations) || o.animations
  23756. }
  23757. for (let i = 0; i < clipArray.length; i++) {
  23758. if (clipArray[i].name === name) {
  23759. return clipArray[i]
  23760. }
  23761. }
  23762. return null
  23763. }
  23764. static CreateClipsFromMorphTargetSequences(morphTargets, fps, noLoop) {
  23765. const animationToMorphTargets = {}
  23766. // tested with https://regex101.com/ on trick sequences
  23767. // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
  23768. const pattern = /^([\w-]*?)([\d]+)$/
  23769. // sort morph target names into animation groups based
  23770. // patterns like Walk_001, Walk_002, Run_001, Run_002
  23771. for (let i = 0, il = morphTargets.length; i < il; i++) {
  23772. const morphTarget = morphTargets[i]
  23773. const parts = morphTarget.name.match(pattern)
  23774. if (parts && parts.length > 1) {
  23775. const name = parts[1]
  23776. let animationMorphTargets = animationToMorphTargets[name]
  23777. if (!animationMorphTargets) {
  23778. animationToMorphTargets[name] = animationMorphTargets = []
  23779. }
  23780. animationMorphTargets.push(morphTarget)
  23781. }
  23782. }
  23783. const clips = []
  23784. for (const name in animationToMorphTargets) {
  23785. clips.push(this.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop))
  23786. }
  23787. return clips
  23788. }
  23789. // parse the animation.hierarchy format
  23790. static parseAnimation(animation, bones) {
  23791. if (!animation) {
  23792. console.error('THREE.AnimationClip: No animation in JSONLoader data.')
  23793. return null
  23794. }
  23795. const addNonemptyTrack = function(trackType, trackName, animationKeys, propertyName, destTracks) {
  23796. // only return track if there are actually keys.
  23797. if (animationKeys.length !== 0) {
  23798. const times = []
  23799. const values = []
  23800. AnimationUtils.flattenJSON(animationKeys, times, values, propertyName)
  23801. // empty keys are filtered out, so check again
  23802. if (times.length !== 0) {
  23803. destTracks.push(new trackType(trackName, times, values))
  23804. }
  23805. }
  23806. }
  23807. const tracks = []
  23808. const clipName = animation.name || 'default'
  23809. const fps = animation.fps || 30
  23810. const blendMode = animation.blendMode
  23811. // automatic length determination in AnimationClip.
  23812. let duration = animation.length || -1
  23813. const hierarchyTracks = animation.hierarchy || []
  23814. for (let h = 0; h < hierarchyTracks.length; h++) {
  23815. const animationKeys = hierarchyTracks[h].keys
  23816. // skip empty tracks
  23817. if (!animationKeys || animationKeys.length === 0) continue
  23818. // process morph targets
  23819. if (animationKeys[0].morphTargets) {
  23820. // figure out all morph targets used in this track
  23821. const morphTargetNames = {}
  23822. let k
  23823. for (k = 0; k < animationKeys.length; k++) {
  23824. if (animationKeys[k].morphTargets) {
  23825. for (let m = 0; m < animationKeys[k].morphTargets.length; m++) {
  23826. morphTargetNames[animationKeys[k].morphTargets[m]] = -1
  23827. }
  23828. }
  23829. }
  23830. // create a track for each morph target with all zero
  23831. // morphTargetInfluences except for the keys in which
  23832. // the morphTarget is named.
  23833. for (const morphTargetName in morphTargetNames) {
  23834. const times = []
  23835. const values = []
  23836. for (let m = 0; m !== animationKeys[k].morphTargets.length; ++m) {
  23837. const animationKey = animationKeys[k]
  23838. times.push(animationKey.time)
  23839. values.push(animationKey.morphTarget === morphTargetName ? 1 : 0)
  23840. }
  23841. tracks.push(new NumberKeyframeTrack('.morphTargetInfluence[' + morphTargetName + ']', times, values))
  23842. }
  23843. duration = morphTargetNames.length * fps
  23844. } else {
  23845. // ...assume skeletal animation
  23846. const boneName = '.bones[' + bones[h].name + ']'
  23847. addNonemptyTrack(VectorKeyframeTrack, boneName + '.position', animationKeys, 'pos', tracks)
  23848. addNonemptyTrack(QuaternionKeyframeTrack, boneName + '.quaternion', animationKeys, 'rot', tracks)
  23849. addNonemptyTrack(VectorKeyframeTrack, boneName + '.scale', animationKeys, 'scl', tracks)
  23850. }
  23851. }
  23852. if (tracks.length === 0) {
  23853. return null
  23854. }
  23855. const clip = new this(clipName, duration, tracks, blendMode)
  23856. return clip
  23857. }
  23858. resetDuration() {
  23859. const tracks = this.tracks
  23860. let duration = 0
  23861. for (let i = 0, n = tracks.length; i !== n; ++i) {
  23862. const track = this.tracks[i]
  23863. duration = Math.max(duration, track.times[track.times.length - 1])
  23864. }
  23865. this.duration = duration
  23866. return this
  23867. }
  23868. trim() {
  23869. for (let i = 0; i < this.tracks.length; i++) {
  23870. this.tracks[i].trim(0, this.duration)
  23871. }
  23872. return this
  23873. }
  23874. validate() {
  23875. let valid = true
  23876. for (let i = 0; i < this.tracks.length; i++) {
  23877. valid = valid && this.tracks[i].validate()
  23878. }
  23879. return valid
  23880. }
  23881. optimize() {
  23882. for (let i = 0; i < this.tracks.length; i++) {
  23883. this.tracks[i].optimize()
  23884. }
  23885. return this
  23886. }
  23887. clone() {
  23888. const tracks = []
  23889. for (let i = 0; i < this.tracks.length; i++) {
  23890. tracks.push(this.tracks[i].clone())
  23891. }
  23892. return new this.constructor(this.name, this.duration, tracks, this.blendMode)
  23893. }
  23894. toJSON() {
  23895. return this.constructor.toJSON(this)
  23896. }
  23897. }
  23898. function getTrackTypeForValueTypeName(typeName) {
  23899. switch (typeName.toLowerCase()) {
  23900. case 'scalar':
  23901. case 'double':
  23902. case 'float':
  23903. case 'number':
  23904. case 'integer':
  23905. return NumberKeyframeTrack
  23906. case 'vector':
  23907. case 'vector2':
  23908. case 'vector3':
  23909. case 'vector4':
  23910. return VectorKeyframeTrack
  23911. case 'color':
  23912. return ColorKeyframeTrack
  23913. case 'quaternion':
  23914. return QuaternionKeyframeTrack
  23915. case 'bool':
  23916. case 'boolean':
  23917. return BooleanKeyframeTrack
  23918. case 'string':
  23919. return StringKeyframeTrack
  23920. }
  23921. throw new Error('THREE.KeyframeTrack: Unsupported typeName: ' + typeName)
  23922. }
  23923. function parseKeyframeTrack(json) {
  23924. if (json.type === undefined) {
  23925. throw new Error('THREE.KeyframeTrack: track type undefined, can not parse')
  23926. }
  23927. const trackType = getTrackTypeForValueTypeName(json.type)
  23928. if (json.times === undefined) {
  23929. const times = [],
  23930. values = []
  23931. AnimationUtils.flattenJSON(json.keys, times, values, 'value')
  23932. json.times = times
  23933. json.values = values
  23934. }
  23935. // derived classes can define a static parse method
  23936. if (trackType.parse !== undefined) {
  23937. return trackType.parse(json)
  23938. } else {
  23939. // by default, we assume a constructor compatible with the base
  23940. return new trackType(json.name, json.times, json.values, json.interpolation)
  23941. }
  23942. }
  23943. const Cache = {
  23944. enabled: false,
  23945. files: {},
  23946. add: function(key, file) {
  23947. if (this.enabled === false) return
  23948. // console.log( 'THREE.Cache', 'Adding key:', key );
  23949. this.files[key] = file
  23950. },
  23951. get: function(key) {
  23952. if (this.enabled === false) return
  23953. // console.log( 'THREE.Cache', 'Checking key:', key );
  23954. return this.files[key]
  23955. },
  23956. remove: function(key) {
  23957. delete this.files[key]
  23958. },
  23959. clear: function() {
  23960. this.files = {}
  23961. }
  23962. }
  23963. class LoadingManager {
  23964. constructor(onLoad, onProgress, onError) {
  23965. const scope = this
  23966. let isLoading = false
  23967. let itemsLoaded = 0
  23968. let itemsTotal = 0
  23969. let urlModifier = undefined
  23970. const handlers = []
  23971. // Refer to #5689 for the reason why we don't set .onStart
  23972. // in the constructor
  23973. this.onStart = undefined
  23974. this.onLoad = onLoad
  23975. this.onProgress = onProgress
  23976. this.onError = onError
  23977. this.itemStart = function(url) {
  23978. itemsTotal++
  23979. if (isLoading === false) {
  23980. if (scope.onStart !== undefined) {
  23981. scope.onStart(url, itemsLoaded, itemsTotal)
  23982. }
  23983. }
  23984. isLoading = true
  23985. }
  23986. this.itemEnd = function(url) {
  23987. itemsLoaded++
  23988. if (scope.onProgress !== undefined) {
  23989. scope.onProgress(url, itemsLoaded, itemsTotal)
  23990. }
  23991. if (itemsLoaded === itemsTotal) {
  23992. isLoading = false
  23993. if (scope.onLoad !== undefined) {
  23994. scope.onLoad()
  23995. }
  23996. }
  23997. }
  23998. this.itemError = function(url) {
  23999. if (scope.onError !== undefined) {
  24000. scope.onError(url)
  24001. }
  24002. }
  24003. this.resolveURL = function(url) {
  24004. if (urlModifier) {
  24005. return urlModifier(url)
  24006. }
  24007. return url
  24008. }
  24009. this.setURLModifier = function(transform) {
  24010. urlModifier = transform
  24011. return this
  24012. }
  24013. this.addHandler = function(regex, loader) {
  24014. handlers.push(regex, loader)
  24015. return this
  24016. }
  24017. this.removeHandler = function(regex) {
  24018. const index = handlers.indexOf(regex)
  24019. if (index !== -1) {
  24020. handlers.splice(index, 2)
  24021. }
  24022. return this
  24023. }
  24024. this.getHandler = function(file) {
  24025. for (let i = 0, l = handlers.length; i < l; i += 2) {
  24026. const regex = handlers[i]
  24027. const loader = handlers[i + 1]
  24028. if (regex.global) regex.lastIndex = 0 // see #17920
  24029. if (regex.test(file)) {
  24030. return loader
  24031. }
  24032. }
  24033. return null
  24034. }
  24035. }
  24036. }
  24037. const DefaultLoadingManager = new LoadingManager()
  24038. class Loader {
  24039. constructor(manager) {
  24040. this.manager = manager !== undefined ? manager : DefaultLoadingManager
  24041. this.crossOrigin = 'anonymous'
  24042. this.withCredentials = false
  24043. this.path = ''
  24044. this.resourcePath = ''
  24045. this.requestHeader = {}
  24046. }
  24047. load(/* url, onLoad, onProgress, onError */) {}
  24048. loadAsync(url, onProgress) {
  24049. const scope = this
  24050. return new Promise(function(resolve, reject) {
  24051. scope.load(url, resolve, onProgress, reject)
  24052. })
  24053. }
  24054. parse(/* data */) {}
  24055. setCrossOrigin(crossOrigin) {
  24056. this.crossOrigin = crossOrigin
  24057. return this
  24058. }
  24059. setWithCredentials(value) {
  24060. this.withCredentials = value
  24061. return this
  24062. }
  24063. setPath(path) {
  24064. this.path = path
  24065. return this
  24066. }
  24067. setResourcePath(resourcePath) {
  24068. this.resourcePath = resourcePath
  24069. return this
  24070. }
  24071. setRequestHeader(requestHeader) {
  24072. this.requestHeader = requestHeader
  24073. return this
  24074. }
  24075. }
  24076. const loading = {}
  24077. class FileLoader extends Loader {
  24078. constructor(manager) {
  24079. super(manager)
  24080. }
  24081. load(url, onLoad, onProgress, onError) {
  24082. if (url === undefined) url = ''
  24083. if (this.path !== undefined) url = this.path + url
  24084. url = this.manager.resolveURL(url)
  24085. const cached = Cache.get(url)
  24086. if (cached !== undefined) {
  24087. this.manager.itemStart(url)
  24088. setTimeout(() => {
  24089. if (onLoad) onLoad(cached)
  24090. this.manager.itemEnd(url)
  24091. }, 0)
  24092. return cached
  24093. }
  24094. // Check if request is duplicate
  24095. if (loading[url] !== undefined) {
  24096. loading[url].push({
  24097. onLoad: onLoad,
  24098. onProgress: onProgress,
  24099. onError: onError
  24100. })
  24101. return
  24102. }
  24103. // Initialise array for duplicate requests
  24104. loading[url] = []
  24105. loading[url].push({
  24106. onLoad: onLoad,
  24107. onProgress: onProgress,
  24108. onError: onError
  24109. })
  24110. // create request
  24111. const req = new Request(url, {
  24112. headers: new Headers(this.requestHeader),
  24113. credentials: this.withCredentials ? 'include' : 'same-origin'
  24114. // An abort controller could be added within a future PR
  24115. })
  24116. // record states ( avoid data race )
  24117. const mimeType = this.mimeType
  24118. const responseType = this.responseType
  24119. // start the fetch
  24120. fetch(req)
  24121. .then(response => {
  24122. if (response.status === 200 || response.status === 0) {
  24123. // Some browsers return HTTP Status 0 when using non-http protocol
  24124. // e.g. 'file://' or 'data://'. Handle as success.
  24125. if (response.status === 0) {
  24126. console.warn('THREE.FileLoader: HTTP Status 0 received.')
  24127. }
  24128. // Workaround: Checking if response.body === undefined for Alipay browser #23548
  24129. if (typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined) {
  24130. return response
  24131. }
  24132. const callbacks = loading[url]
  24133. const reader = response.body.getReader()
  24134. const contentLength = response.headers.get('Content-Length')
  24135. const total = contentLength ? parseInt(contentLength) : 0
  24136. const lengthComputable = total !== 0
  24137. let loaded = 0
  24138. // periodically read data into the new stream tracking while download progress
  24139. const stream = new ReadableStream({
  24140. start(controller) {
  24141. readData()
  24142. function readData() {
  24143. reader.read().then(({ done, value }) => {
  24144. if (done) {
  24145. controller.close()
  24146. } else {
  24147. loaded += value.byteLength
  24148. const event = new ProgressEvent('progress', { lengthComputable, loaded, total })
  24149. for (let i = 0, il = callbacks.length; i < il; i++) {
  24150. const callback = callbacks[i]
  24151. if (callback.onProgress) callback.onProgress(event)
  24152. }
  24153. controller.enqueue(value)
  24154. readData()
  24155. }
  24156. })
  24157. }
  24158. }
  24159. })
  24160. return new Response(stream)
  24161. } else {
  24162. throw Error(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`)
  24163. }
  24164. })
  24165. .then(response => {
  24166. switch (responseType) {
  24167. case 'arraybuffer':
  24168. return response.arrayBuffer()
  24169. case 'blob':
  24170. return response.blob()
  24171. case 'document':
  24172. return response.text().then(text => {
  24173. const parser = new DOMParser()
  24174. return parser.parseFromString(text, mimeType)
  24175. })
  24176. case 'json':
  24177. return response.json()
  24178. default:
  24179. if (mimeType === undefined) {
  24180. return response.text()
  24181. } else {
  24182. // sniff encoding
  24183. const re = /charset="?([^;"\s]*)"?/i
  24184. const exec = re.exec(mimeType)
  24185. const label = exec && exec[1] ? exec[1].toLowerCase() : undefined
  24186. const decoder = new TextDecoder(label)
  24187. return response.arrayBuffer().then(ab => decoder.decode(ab))
  24188. }
  24189. }
  24190. })
  24191. .then(data => {
  24192. // Add to cache only on HTTP success, so that we do not cache
  24193. // error response bodies as proper responses to requests.
  24194. Cache.add(url, data)
  24195. const callbacks = loading[url]
  24196. delete loading[url]
  24197. for (let i = 0, il = callbacks.length; i < il; i++) {
  24198. const callback = callbacks[i]
  24199. if (callback.onLoad) callback.onLoad(data)
  24200. }
  24201. })
  24202. .catch(err => {
  24203. // Abort errors and other errors are handled the same
  24204. const callbacks = loading[url]
  24205. if (callbacks === undefined) {
  24206. // When onLoad was called and url was deleted in `loading`
  24207. this.manager.itemError(url)
  24208. throw err
  24209. }
  24210. delete loading[url]
  24211. for (let i = 0, il = callbacks.length; i < il; i++) {
  24212. const callback = callbacks[i]
  24213. if (callback.onError) callback.onError(err)
  24214. }
  24215. this.manager.itemError(url)
  24216. })
  24217. .finally(() => {
  24218. this.manager.itemEnd(url)
  24219. })
  24220. this.manager.itemStart(url)
  24221. }
  24222. setResponseType(value) {
  24223. this.responseType = value
  24224. return this
  24225. }
  24226. setMimeType(value) {
  24227. this.mimeType = value
  24228. return this
  24229. }
  24230. }
  24231. class AnimationLoader extends Loader {
  24232. constructor(manager) {
  24233. super(manager)
  24234. }
  24235. load(url, onLoad, onProgress, onError) {
  24236. const scope = this
  24237. const loader = new FileLoader(this.manager)
  24238. loader.setPath(this.path)
  24239. loader.setRequestHeader(this.requestHeader)
  24240. loader.setWithCredentials(this.withCredentials)
  24241. loader.load(
  24242. url,
  24243. function(text) {
  24244. try {
  24245. onLoad(scope.parse(JSON.parse(text)))
  24246. } catch (e) {
  24247. if (onError) {
  24248. onError(e)
  24249. } else {
  24250. console.error(e)
  24251. }
  24252. scope.manager.itemError(url)
  24253. }
  24254. },
  24255. onProgress,
  24256. onError
  24257. )
  24258. }
  24259. parse(json) {
  24260. const animations = []
  24261. for (let i = 0; i < json.length; i++) {
  24262. const clip = AnimationClip.parse(json[i])
  24263. animations.push(clip)
  24264. }
  24265. return animations
  24266. }
  24267. }
  24268. /**
  24269. * Abstract Base class to block based textures loader (dds, pvr, ...)
  24270. *
  24271. * Sub classes have to implement the parse() method which will be used in load().
  24272. */
  24273. class CompressedTextureLoader extends Loader {
  24274. constructor(manager) {
  24275. super(manager)
  24276. }
  24277. load(url, onLoad, onProgress, onError) {
  24278. const scope = this
  24279. const images = []
  24280. const texture = new CompressedTexture()
  24281. const loader = new FileLoader(this.manager)
  24282. loader.setPath(this.path)
  24283. loader.setResponseType('arraybuffer')
  24284. loader.setRequestHeader(this.requestHeader)
  24285. loader.setWithCredentials(scope.withCredentials)
  24286. let loaded = 0
  24287. function loadTexture(i) {
  24288. loader.load(
  24289. url[i],
  24290. function(buffer) {
  24291. const texDatas = scope.parse(buffer, true)
  24292. images[i] = {
  24293. width: texDatas.width,
  24294. height: texDatas.height,
  24295. format: texDatas.format,
  24296. mipmaps: texDatas.mipmaps
  24297. }
  24298. loaded += 1
  24299. if (loaded === 6) {
  24300. if (texDatas.mipmapCount === 1) texture.minFilter = LinearFilter
  24301. texture.image = images
  24302. texture.format = texDatas.format
  24303. texture.needsUpdate = true
  24304. if (onLoad) onLoad(texture)
  24305. }
  24306. },
  24307. onProgress,
  24308. onError
  24309. )
  24310. }
  24311. if (Array.isArray(url)) {
  24312. for (let i = 0, il = url.length; i < il; ++i) {
  24313. loadTexture(i)
  24314. }
  24315. } else {
  24316. // compressed cubemap texture stored in a single DDS file
  24317. loader.load(
  24318. url,
  24319. function(buffer) {
  24320. const texDatas = scope.parse(buffer, true)
  24321. if (texDatas.isCubemap) {
  24322. const faces = texDatas.mipmaps.length / texDatas.mipmapCount
  24323. for (let f = 0; f < faces; f++) {
  24324. images[f] = { mipmaps: [] }
  24325. for (let i = 0; i < texDatas.mipmapCount; i++) {
  24326. images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i])
  24327. images[f].format = texDatas.format
  24328. images[f].width = texDatas.width
  24329. images[f].height = texDatas.height
  24330. }
  24331. }
  24332. texture.image = images
  24333. } else {
  24334. texture.image.width = texDatas.width
  24335. texture.image.height = texDatas.height
  24336. texture.mipmaps = texDatas.mipmaps
  24337. }
  24338. if (texDatas.mipmapCount === 1) {
  24339. texture.minFilter = LinearFilter
  24340. }
  24341. texture.format = texDatas.format
  24342. texture.needsUpdate = true
  24343. if (onLoad) onLoad(texture)
  24344. },
  24345. onProgress,
  24346. onError
  24347. )
  24348. }
  24349. return texture
  24350. }
  24351. }
  24352. class ImageLoader extends Loader {
  24353. constructor(manager) {
  24354. super(manager)
  24355. }
  24356. load(url, onLoad, onProgress, onError) {
  24357. if (this.path !== undefined) url = this.path + url
  24358. url = this.manager.resolveURL(url)
  24359. const scope = this
  24360. const cached = Cache.get(url)
  24361. if (cached !== undefined) {
  24362. scope.manager.itemStart(url)
  24363. setTimeout(function() {
  24364. if (onLoad) onLoad(cached)
  24365. scope.manager.itemEnd(url)
  24366. }, 0)
  24367. return cached
  24368. }
  24369. const image = createElementNS('img')
  24370. function onImageLoad() {
  24371. removeEventListeners()
  24372. Cache.add(url, this)
  24373. if (onLoad) onLoad(this)
  24374. scope.manager.itemEnd(url)
  24375. }
  24376. function onImageError(event) {
  24377. removeEventListeners()
  24378. if (onError) onError(event)
  24379. scope.manager.itemError(url)
  24380. scope.manager.itemEnd(url)
  24381. }
  24382. function removeEventListeners() {
  24383. image.removeEventListener('load', onImageLoad, false)
  24384. image.removeEventListener('error', onImageError, false)
  24385. }
  24386. image.addEventListener('load', onImageLoad, false)
  24387. image.addEventListener('error', onImageError, false)
  24388. if (url.slice(0, 5) !== 'data:') {
  24389. if (this.crossOrigin !== undefined) image.crossOrigin = this.crossOrigin
  24390. }
  24391. scope.manager.itemStart(url)
  24392. image.src = url
  24393. return image
  24394. }
  24395. }
  24396. class CubeTextureLoader extends Loader {
  24397. constructor(manager) {
  24398. super(manager)
  24399. }
  24400. load(urls, onLoad, onProgress, onError) {
  24401. const texture = new CubeTexture()
  24402. const loader = new ImageLoader(this.manager)
  24403. loader.setCrossOrigin(this.crossOrigin)
  24404. loader.setPath(this.path)
  24405. let loaded = 0
  24406. function loadTexture(i) {
  24407. loader.load(
  24408. urls[i],
  24409. function(image) {
  24410. texture.images[i] = image
  24411. loaded++
  24412. if (loaded === 6) {
  24413. texture.needsUpdate = true
  24414. if (onLoad) onLoad(texture)
  24415. }
  24416. },
  24417. undefined,
  24418. onError
  24419. )
  24420. }
  24421. for (let i = 0; i < urls.length; ++i) {
  24422. loadTexture(i)
  24423. }
  24424. return texture
  24425. }
  24426. }
  24427. /**
  24428. * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
  24429. *
  24430. * Sub classes have to implement the parse() method which will be used in load().
  24431. */
  24432. class DataTextureLoader extends Loader {
  24433. constructor(manager) {
  24434. super(manager)
  24435. }
  24436. load(url, onLoad, onProgress, onError) {
  24437. const scope = this
  24438. const texture = new DataTexture()
  24439. const loader = new FileLoader(this.manager)
  24440. loader.setResponseType('arraybuffer')
  24441. loader.setRequestHeader(this.requestHeader)
  24442. loader.setPath(this.path)
  24443. loader.setWithCredentials(scope.withCredentials)
  24444. loader.load(
  24445. url,
  24446. function(buffer) {
  24447. const texData = scope.parse(buffer)
  24448. if (!texData) return
  24449. if (texData.image !== undefined) {
  24450. texture.image = texData.image
  24451. } else if (texData.data !== undefined) {
  24452. texture.image.width = texData.width
  24453. texture.image.height = texData.height
  24454. texture.image.data = texData.data
  24455. }
  24456. texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping
  24457. texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping
  24458. texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter
  24459. texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter
  24460. texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1
  24461. if (texData.encoding !== undefined) {
  24462. texture.encoding = texData.encoding
  24463. }
  24464. if (texData.flipY !== undefined) {
  24465. texture.flipY = texData.flipY
  24466. }
  24467. if (texData.format !== undefined) {
  24468. texture.format = texData.format
  24469. }
  24470. if (texData.type !== undefined) {
  24471. texture.type = texData.type
  24472. }
  24473. if (texData.mipmaps !== undefined) {
  24474. texture.mipmaps = texData.mipmaps
  24475. texture.minFilter = LinearMipmapLinearFilter // presumably...
  24476. }
  24477. if (texData.mipmapCount === 1) {
  24478. texture.minFilter = LinearFilter
  24479. }
  24480. if (texData.generateMipmaps !== undefined) {
  24481. texture.generateMipmaps = texData.generateMipmaps
  24482. }
  24483. texture.needsUpdate = true
  24484. if (onLoad) onLoad(texture, texData)
  24485. },
  24486. onProgress,
  24487. onError
  24488. )
  24489. return texture
  24490. }
  24491. }
  24492. class TextureLoader extends Loader {
  24493. constructor(manager) {
  24494. super(manager)
  24495. }
  24496. load(url, onLoad, onProgress, onError) {
  24497. const texture = new Texture()
  24498. const loader = new ImageLoader(this.manager)
  24499. loader.setCrossOrigin(this.crossOrigin)
  24500. loader.setPath(this.path)
  24501. loader.load(
  24502. url,
  24503. function(image) {
  24504. texture.image = image
  24505. texture.needsUpdate = true
  24506. if (onLoad !== undefined) {
  24507. onLoad(texture)
  24508. }
  24509. },
  24510. onProgress,
  24511. onError
  24512. )
  24513. return texture
  24514. }
  24515. }
  24516. class Light extends Object3D {
  24517. constructor(color, intensity = 1) {
  24518. super()
  24519. this.isLight = true
  24520. this.type = 'Light'
  24521. this.color = new Color(color)
  24522. this.intensity = intensity
  24523. }
  24524. dispose() {
  24525. // Empty here in base class; some subclasses override.
  24526. }
  24527. copy(source, recursive) {
  24528. super.copy(source, recursive)
  24529. this.color.copy(source.color)
  24530. this.intensity = source.intensity
  24531. return this
  24532. }
  24533. toJSON(meta) {
  24534. const data = super.toJSON(meta)
  24535. data.object.color = this.color.getHex()
  24536. data.object.intensity = this.intensity
  24537. if (this.groundColor !== undefined) data.object.groundColor = this.groundColor.getHex()
  24538. if (this.distance !== undefined) data.object.distance = this.distance
  24539. if (this.angle !== undefined) data.object.angle = this.angle
  24540. if (this.decay !== undefined) data.object.decay = this.decay
  24541. if (this.penumbra !== undefined) data.object.penumbra = this.penumbra
  24542. if (this.shadow !== undefined) data.object.shadow = this.shadow.toJSON()
  24543. return data
  24544. }
  24545. }
  24546. class HemisphereLight extends Light {
  24547. constructor(skyColor, groundColor, intensity) {
  24548. super(skyColor, intensity)
  24549. this.isHemisphereLight = true
  24550. this.type = 'HemisphereLight'
  24551. this.position.copy(Object3D.DefaultUp)
  24552. this.updateMatrix()
  24553. this.groundColor = new Color(groundColor)
  24554. }
  24555. copy(source, recursive) {
  24556. super.copy(source, recursive)
  24557. this.groundColor.copy(source.groundColor)
  24558. return this
  24559. }
  24560. }
  24561. const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4()
  24562. const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3()
  24563. const _lookTarget$1 = /*@__PURE__*/ new Vector3()
  24564. class LightShadow {
  24565. constructor(camera) {
  24566. this.camera = camera
  24567. this.bias = 0
  24568. this.normalBias = 0
  24569. this.radius = 1
  24570. this.blurSamples = 8
  24571. this.mapSize = new Vector2(512, 512)
  24572. this.map = null
  24573. this.mapPass = null
  24574. this.matrix = new Matrix4()
  24575. this.autoUpdate = true
  24576. this.needsUpdate = false
  24577. this._frustum = new Frustum()
  24578. this._frameExtents = new Vector2(1, 1)
  24579. this._viewportCount = 1
  24580. this._viewports = [new Vector4(0, 0, 1, 1)]
  24581. }
  24582. getViewportCount() {
  24583. return this._viewportCount
  24584. }
  24585. getFrustum() {
  24586. return this._frustum
  24587. }
  24588. updateMatrices(light) {
  24589. const shadowCamera = this.camera
  24590. const shadowMatrix = this.matrix
  24591. _lightPositionWorld$1.setFromMatrixPosition(light.matrixWorld)
  24592. shadowCamera.position.copy(_lightPositionWorld$1)
  24593. _lookTarget$1.setFromMatrixPosition(light.target.matrixWorld)
  24594. shadowCamera.lookAt(_lookTarget$1)
  24595. shadowCamera.updateMatrixWorld()
  24596. _projScreenMatrix$1.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse)
  24597. this._frustum.setFromProjectionMatrix(_projScreenMatrix$1)
  24598. shadowMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0)
  24599. shadowMatrix.multiply(shadowCamera.projectionMatrix)
  24600. shadowMatrix.multiply(shadowCamera.matrixWorldInverse)
  24601. }
  24602. getViewport(viewportIndex) {
  24603. return this._viewports[viewportIndex]
  24604. }
  24605. getFrameExtents() {
  24606. return this._frameExtents
  24607. }
  24608. dispose() {
  24609. if (this.map) {
  24610. this.map.dispose()
  24611. }
  24612. if (this.mapPass) {
  24613. this.mapPass.dispose()
  24614. }
  24615. }
  24616. copy(source) {
  24617. this.camera = source.camera.clone()
  24618. this.bias = source.bias
  24619. this.radius = source.radius
  24620. this.mapSize.copy(source.mapSize)
  24621. return this
  24622. }
  24623. clone() {
  24624. return new this.constructor().copy(this)
  24625. }
  24626. toJSON() {
  24627. const object = {}
  24628. if (this.bias !== 0) object.bias = this.bias
  24629. if (this.normalBias !== 0) object.normalBias = this.normalBias
  24630. if (this.radius !== 1) object.radius = this.radius
  24631. if (this.mapSize.x !== 512 || this.mapSize.y !== 512) object.mapSize = this.mapSize.toArray()
  24632. object.camera = this.camera.toJSON(false).object
  24633. delete object.camera.matrix
  24634. return object
  24635. }
  24636. }
  24637. class SpotLightShadow extends LightShadow {
  24638. constructor() {
  24639. super(new PerspectiveCamera(50, 1, 0.5, 500))
  24640. this.isSpotLightShadow = true
  24641. this.focus = 1
  24642. }
  24643. updateMatrices(light) {
  24644. const camera = this.camera
  24645. const fov = RAD2DEG * 2 * light.angle * this.focus
  24646. const aspect = this.mapSize.width / this.mapSize.height
  24647. const far = light.distance || camera.far
  24648. if (fov !== camera.fov || aspect !== camera.aspect || far !== camera.far) {
  24649. camera.fov = fov
  24650. camera.aspect = aspect
  24651. camera.far = far
  24652. camera.updateProjectionMatrix()
  24653. }
  24654. super.updateMatrices(light)
  24655. }
  24656. copy(source) {
  24657. super.copy(source)
  24658. this.focus = source.focus
  24659. return this
  24660. }
  24661. }
  24662. class SpotLight extends Light {
  24663. constructor(color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 1) {
  24664. super(color, intensity)
  24665. this.isSpotLight = true
  24666. this.type = 'SpotLight'
  24667. this.position.copy(Object3D.DefaultUp)
  24668. this.updateMatrix()
  24669. this.target = new Object3D()
  24670. this.distance = distance
  24671. this.angle = angle
  24672. this.penumbra = penumbra
  24673. this.decay = decay // for physically correct lights, should be 2.
  24674. this.shadow = new SpotLightShadow()
  24675. }
  24676. get power() {
  24677. // compute the light's luminous power (in lumens) from its intensity (in candela)
  24678. // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
  24679. return this.intensity * Math.PI
  24680. }
  24681. set power(power) {
  24682. // set the light's intensity (in candela) from the desired luminous power (in lumens)
  24683. this.intensity = power / Math.PI
  24684. }
  24685. dispose() {
  24686. this.shadow.dispose()
  24687. }
  24688. copy(source, recursive) {
  24689. super.copy(source, recursive)
  24690. this.distance = source.distance
  24691. this.angle = source.angle
  24692. this.penumbra = source.penumbra
  24693. this.decay = source.decay
  24694. this.target = source.target.clone()
  24695. this.shadow = source.shadow.clone()
  24696. return this
  24697. }
  24698. }
  24699. const _projScreenMatrix = /*@__PURE__*/ new Matrix4()
  24700. const _lightPositionWorld = /*@__PURE__*/ new Vector3()
  24701. const _lookTarget = /*@__PURE__*/ new Vector3()
  24702. class PointLightShadow extends LightShadow {
  24703. constructor() {
  24704. super(new PerspectiveCamera(90, 1, 0.5, 500))
  24705. this.isPointLightShadow = true
  24706. this._frameExtents = new Vector2(4, 2)
  24707. this._viewportCount = 6
  24708. this._viewports = [
  24709. // These viewports map a cube-map onto a 2D texture with the
  24710. // following orientation:
  24711. //
  24712. // xzXZ
  24713. // y Y
  24714. //
  24715. // X - Positive x direction
  24716. // x - Negative x direction
  24717. // Y - Positive y direction
  24718. // y - Negative y direction
  24719. // Z - Positive z direction
  24720. // z - Negative z direction
  24721. // positive X
  24722. new Vector4(2, 1, 1, 1),
  24723. // negative X
  24724. new Vector4(0, 1, 1, 1),
  24725. // positive Z
  24726. new Vector4(3, 1, 1, 1),
  24727. // negative Z
  24728. new Vector4(1, 1, 1, 1),
  24729. // positive Y
  24730. new Vector4(3, 0, 1, 1),
  24731. // negative Y
  24732. new Vector4(1, 0, 1, 1)
  24733. ]
  24734. this._cubeDirections = [new Vector3(1, 0, 0), new Vector3(-1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1), new Vector3(0, 1, 0), new Vector3(0, -1, 0)]
  24735. this._cubeUps = [new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, -1)]
  24736. }
  24737. updateMatrices(light, viewportIndex = 0) {
  24738. const camera = this.camera
  24739. const shadowMatrix = this.matrix
  24740. const far = light.distance || camera.far
  24741. if (far !== camera.far) {
  24742. camera.far = far
  24743. camera.updateProjectionMatrix()
  24744. }
  24745. _lightPositionWorld.setFromMatrixPosition(light.matrixWorld)
  24746. camera.position.copy(_lightPositionWorld)
  24747. _lookTarget.copy(camera.position)
  24748. _lookTarget.add(this._cubeDirections[viewportIndex])
  24749. camera.up.copy(this._cubeUps[viewportIndex])
  24750. camera.lookAt(_lookTarget)
  24751. camera.updateMatrixWorld()
  24752. shadowMatrix.makeTranslation(-_lightPositionWorld.x, -_lightPositionWorld.y, -_lightPositionWorld.z)
  24753. _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
  24754. this._frustum.setFromProjectionMatrix(_projScreenMatrix)
  24755. }
  24756. }
  24757. class PointLight extends Light {
  24758. constructor(color, intensity, distance = 0, decay = 1) {
  24759. super(color, intensity)
  24760. this.isPointLight = true
  24761. this.type = 'PointLight'
  24762. this.distance = distance
  24763. this.decay = decay // for physically correct lights, should be 2.
  24764. this.shadow = new PointLightShadow()
  24765. }
  24766. get power() {
  24767. // compute the light's luminous power (in lumens) from its intensity (in candela)
  24768. // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
  24769. return this.intensity * 4 * Math.PI
  24770. }
  24771. set power(power) {
  24772. // set the light's intensity (in candela) from the desired luminous power (in lumens)
  24773. this.intensity = power / (4 * Math.PI)
  24774. }
  24775. dispose() {
  24776. this.shadow.dispose()
  24777. }
  24778. copy(source, recursive) {
  24779. super.copy(source, recursive)
  24780. this.distance = source.distance
  24781. this.decay = source.decay
  24782. this.shadow = source.shadow.clone()
  24783. return this
  24784. }
  24785. }
  24786. class DirectionalLightShadow extends LightShadow {
  24787. constructor() {
  24788. super(new OrthographicCamera(-5, 5, 5, -5, 0.5, 500))
  24789. this.isDirectionalLightShadow = true
  24790. }
  24791. }
  24792. class DirectionalLight extends Light {
  24793. constructor(color, intensity) {
  24794. super(color, intensity)
  24795. this.isDirectionalLight = true
  24796. this.type = 'DirectionalLight'
  24797. this.position.copy(Object3D.DefaultUp)
  24798. this.updateMatrix()
  24799. this.target = new Object3D()
  24800. this.shadow = new DirectionalLightShadow()
  24801. }
  24802. dispose() {
  24803. this.shadow.dispose()
  24804. }
  24805. copy(source) {
  24806. super.copy(source)
  24807. this.target = source.target.clone()
  24808. this.shadow = source.shadow.clone()
  24809. return this
  24810. }
  24811. }
  24812. class AmbientLight extends Light {
  24813. constructor(color, intensity) {
  24814. super(color, intensity)
  24815. this.isAmbientLight = true
  24816. this.type = 'AmbientLight'
  24817. }
  24818. }
  24819. class RectAreaLight extends Light {
  24820. constructor(color, intensity, width = 10, height = 10) {
  24821. super(color, intensity)
  24822. this.isRectAreaLight = true
  24823. this.type = 'RectAreaLight'
  24824. this.width = width
  24825. this.height = height
  24826. }
  24827. get power() {
  24828. // compute the light's luminous power (in lumens) from its intensity (in nits)
  24829. return this.intensity * this.width * this.height * Math.PI
  24830. }
  24831. set power(power) {
  24832. // set the light's intensity (in nits) from the desired luminous power (in lumens)
  24833. this.intensity = power / (this.width * this.height * Math.PI)
  24834. }
  24835. copy(source) {
  24836. super.copy(source)
  24837. this.width = source.width
  24838. this.height = source.height
  24839. return this
  24840. }
  24841. toJSON(meta) {
  24842. const data = super.toJSON(meta)
  24843. data.object.width = this.width
  24844. data.object.height = this.height
  24845. return data
  24846. }
  24847. }
  24848. /**
  24849. * Primary reference:
  24850. * https://graphics.stanford.edu/papers/envmap/envmap.pdf
  24851. *
  24852. * Secondary reference:
  24853. * https://www.ppsloan.org/publications/StupidSH36.pdf
  24854. */
  24855. // 3-band SH defined by 9 coefficients
  24856. class SphericalHarmonics3 {
  24857. constructor() {
  24858. this.isSphericalHarmonics3 = true
  24859. this.coefficients = []
  24860. for (let i = 0; i < 9; i++) {
  24861. this.coefficients.push(new Vector3())
  24862. }
  24863. }
  24864. set(coefficients) {
  24865. for (let i = 0; i < 9; i++) {
  24866. this.coefficients[i].copy(coefficients[i])
  24867. }
  24868. return this
  24869. }
  24870. zero() {
  24871. for (let i = 0; i < 9; i++) {
  24872. this.coefficients[i].set(0, 0, 0)
  24873. }
  24874. return this
  24875. }
  24876. // get the radiance in the direction of the normal
  24877. // target is a Vector3
  24878. getAt(normal, target) {
  24879. // normal is assumed to be unit length
  24880. const x = normal.x,
  24881. y = normal.y,
  24882. z = normal.z
  24883. const coeff = this.coefficients
  24884. // band 0
  24885. target.copy(coeff[0]).multiplyScalar(0.282095)
  24886. // band 1
  24887. target.addScaledVector(coeff[1], 0.488603 * y)
  24888. target.addScaledVector(coeff[2], 0.488603 * z)
  24889. target.addScaledVector(coeff[3], 0.488603 * x)
  24890. // band 2
  24891. target.addScaledVector(coeff[4], 1.092548 * (x * y))
  24892. target.addScaledVector(coeff[5], 1.092548 * (y * z))
  24893. target.addScaledVector(coeff[6], 0.315392 * (3.0 * z * z - 1.0))
  24894. target.addScaledVector(coeff[7], 1.092548 * (x * z))
  24895. target.addScaledVector(coeff[8], 0.546274 * (x * x - y * y))
  24896. return target
  24897. }
  24898. // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
  24899. // target is a Vector3
  24900. // https://graphics.stanford.edu/papers/envmap/envmap.pdf
  24901. getIrradianceAt(normal, target) {
  24902. // normal is assumed to be unit length
  24903. const x = normal.x,
  24904. y = normal.y,
  24905. z = normal.z
  24906. const coeff = this.coefficients
  24907. // band 0
  24908. target.copy(coeff[0]).multiplyScalar(0.886227) // π * 0.282095
  24909. // band 1
  24910. target.addScaledVector(coeff[1], 2.0 * 0.511664 * y) // ( 2 * π / 3 ) * 0.488603
  24911. target.addScaledVector(coeff[2], 2.0 * 0.511664 * z)
  24912. target.addScaledVector(coeff[3], 2.0 * 0.511664 * x)
  24913. // band 2
  24914. target.addScaledVector(coeff[4], 2.0 * 0.429043 * x * y) // ( π / 4 ) * 1.092548
  24915. target.addScaledVector(coeff[5], 2.0 * 0.429043 * y * z)
  24916. target.addScaledVector(coeff[6], 0.743125 * z * z - 0.247708) // ( π / 4 ) * 0.315392 * 3
  24917. target.addScaledVector(coeff[7], 2.0 * 0.429043 * x * z)
  24918. target.addScaledVector(coeff[8], 0.429043 * (x * x - y * y)) // ( π / 4 ) * 0.546274
  24919. return target
  24920. }
  24921. add(sh) {
  24922. for (let i = 0; i < 9; i++) {
  24923. this.coefficients[i].add(sh.coefficients[i])
  24924. }
  24925. return this
  24926. }
  24927. addScaledSH(sh, s) {
  24928. for (let i = 0; i < 9; i++) {
  24929. this.coefficients[i].addScaledVector(sh.coefficients[i], s)
  24930. }
  24931. return this
  24932. }
  24933. scale(s) {
  24934. for (let i = 0; i < 9; i++) {
  24935. this.coefficients[i].multiplyScalar(s)
  24936. }
  24937. return this
  24938. }
  24939. lerp(sh, alpha) {
  24940. for (let i = 0; i < 9; i++) {
  24941. this.coefficients[i].lerp(sh.coefficients[i], alpha)
  24942. }
  24943. return this
  24944. }
  24945. equals(sh) {
  24946. for (let i = 0; i < 9; i++) {
  24947. if (!this.coefficients[i].equals(sh.coefficients[i])) {
  24948. return false
  24949. }
  24950. }
  24951. return true
  24952. }
  24953. copy(sh) {
  24954. return this.set(sh.coefficients)
  24955. }
  24956. clone() {
  24957. return new this.constructor().copy(this)
  24958. }
  24959. fromArray(array, offset = 0) {
  24960. const coefficients = this.coefficients
  24961. for (let i = 0; i < 9; i++) {
  24962. coefficients[i].fromArray(array, offset + i * 3)
  24963. }
  24964. return this
  24965. }
  24966. toArray(array = [], offset = 0) {
  24967. const coefficients = this.coefficients
  24968. for (let i = 0; i < 9; i++) {
  24969. coefficients[i].toArray(array, offset + i * 3)
  24970. }
  24971. return array
  24972. }
  24973. // evaluate the basis functions
  24974. // shBasis is an Array[ 9 ]
  24975. static getBasisAt(normal, shBasis) {
  24976. // normal is assumed to be unit length
  24977. const x = normal.x,
  24978. y = normal.y,
  24979. z = normal.z
  24980. // band 0
  24981. shBasis[0] = 0.282095
  24982. // band 1
  24983. shBasis[1] = 0.488603 * y
  24984. shBasis[2] = 0.488603 * z
  24985. shBasis[3] = 0.488603 * x
  24986. // band 2
  24987. shBasis[4] = 1.092548 * x * y
  24988. shBasis[5] = 1.092548 * y * z
  24989. shBasis[6] = 0.315392 * (3 * z * z - 1)
  24990. shBasis[7] = 1.092548 * x * z
  24991. shBasis[8] = 0.546274 * (x * x - y * y)
  24992. }
  24993. }
  24994. class LightProbe extends Light {
  24995. constructor(sh = new SphericalHarmonics3(), intensity = 1) {
  24996. super(undefined, intensity)
  24997. this.isLightProbe = true
  24998. this.sh = sh
  24999. }
  25000. copy(source) {
  25001. super.copy(source)
  25002. this.sh.copy(source.sh)
  25003. return this
  25004. }
  25005. fromJSON(json) {
  25006. this.intensity = json.intensity // TODO: Move this bit to Light.fromJSON();
  25007. this.sh.fromArray(json.sh)
  25008. return this
  25009. }
  25010. toJSON(meta) {
  25011. const data = super.toJSON(meta)
  25012. data.object.sh = this.sh.toArray()
  25013. return data
  25014. }
  25015. }
  25016. class MaterialLoader extends Loader {
  25017. constructor(manager) {
  25018. super(manager)
  25019. this.textures = {}
  25020. }
  25021. load(url, onLoad, onProgress, onError) {
  25022. const scope = this
  25023. const loader = new FileLoader(scope.manager)
  25024. loader.setPath(scope.path)
  25025. loader.setRequestHeader(scope.requestHeader)
  25026. loader.setWithCredentials(scope.withCredentials)
  25027. loader.load(
  25028. url,
  25029. function(text) {
  25030. try {
  25031. onLoad(scope.parse(JSON.parse(text)))
  25032. } catch (e) {
  25033. if (onError) {
  25034. onError(e)
  25035. } else {
  25036. console.error(e)
  25037. }
  25038. scope.manager.itemError(url)
  25039. }
  25040. },
  25041. onProgress,
  25042. onError
  25043. )
  25044. }
  25045. parse(json) {
  25046. const textures = this.textures
  25047. function getTexture(name) {
  25048. if (textures[name] === undefined) {
  25049. console.warn('THREE.MaterialLoader: Undefined texture', name)
  25050. }
  25051. return textures[name]
  25052. }
  25053. const material = Material.fromType(json.type)
  25054. if (json.uuid !== undefined) material.uuid = json.uuid
  25055. if (json.name !== undefined) material.name = json.name
  25056. if (json.color !== undefined && material.color !== undefined) material.color.setHex(json.color)
  25057. if (json.roughness !== undefined) material.roughness = json.roughness
  25058. if (json.metalness !== undefined) material.metalness = json.metalness
  25059. if (json.sheen !== undefined) material.sheen = json.sheen
  25060. if (json.sheenColor !== undefined) material.sheenColor = new Color().setHex(json.sheenColor)
  25061. if (json.sheenRoughness !== undefined) material.sheenRoughness = json.sheenRoughness
  25062. if (json.emissive !== undefined && material.emissive !== undefined) material.emissive.setHex(json.emissive)
  25063. if (json.specular !== undefined && material.specular !== undefined) material.specular.setHex(json.specular)
  25064. if (json.specularIntensity !== undefined) material.specularIntensity = json.specularIntensity
  25065. if (json.specularColor !== undefined && material.specularColor !== undefined) material.specularColor.setHex(json.specularColor)
  25066. if (json.shininess !== undefined) material.shininess = json.shininess
  25067. if (json.clearcoat !== undefined) material.clearcoat = json.clearcoat
  25068. if (json.clearcoatRoughness !== undefined) material.clearcoatRoughness = json.clearcoatRoughness
  25069. if (json.iridescence !== undefined) material.iridescence = json.iridescence
  25070. if (json.iridescenceIOR !== undefined) material.iridescenceIOR = json.iridescenceIOR
  25071. if (json.iridescenceThicknessRange !== undefined) material.iridescenceThicknessRange = json.iridescenceThicknessRange
  25072. if (json.transmission !== undefined) material.transmission = json.transmission
  25073. if (json.thickness !== undefined) material.thickness = json.thickness
  25074. if (json.attenuationDistance !== undefined) material.attenuationDistance = json.attenuationDistance
  25075. if (json.attenuationColor !== undefined && material.attenuationColor !== undefined) material.attenuationColor.setHex(json.attenuationColor)
  25076. if (json.fog !== undefined) material.fog = json.fog
  25077. if (json.flatShading !== undefined) material.flatShading = json.flatShading
  25078. if (json.blending !== undefined) material.blending = json.blending
  25079. if (json.combine !== undefined) material.combine = json.combine
  25080. if (json.side !== undefined) material.side = json.side
  25081. if (json.shadowSide !== undefined) material.shadowSide = json.shadowSide
  25082. if (json.opacity !== undefined) material.opacity = json.opacity
  25083. if (json.transparent !== undefined) material.transparent = json.transparent
  25084. if (json.alphaTest !== undefined) material.alphaTest = json.alphaTest
  25085. if (json.depthTest !== undefined) material.depthTest = json.depthTest
  25086. if (json.depthWrite !== undefined) material.depthWrite = json.depthWrite
  25087. if (json.colorWrite !== undefined) material.colorWrite = json.colorWrite
  25088. if (json.stencilWrite !== undefined) material.stencilWrite = json.stencilWrite
  25089. if (json.stencilWriteMask !== undefined) material.stencilWriteMask = json.stencilWriteMask
  25090. if (json.stencilFunc !== undefined) material.stencilFunc = json.stencilFunc
  25091. if (json.stencilRef !== undefined) material.stencilRef = json.stencilRef
  25092. if (json.stencilFuncMask !== undefined) material.stencilFuncMask = json.stencilFuncMask
  25093. if (json.stencilFail !== undefined) material.stencilFail = json.stencilFail
  25094. if (json.stencilZFail !== undefined) material.stencilZFail = json.stencilZFail
  25095. if (json.stencilZPass !== undefined) material.stencilZPass = json.stencilZPass
  25096. if (json.wireframe !== undefined) material.wireframe = json.wireframe
  25097. if (json.wireframeLinewidth !== undefined) material.wireframeLinewidth = json.wireframeLinewidth
  25098. if (json.wireframeLinecap !== undefined) material.wireframeLinecap = json.wireframeLinecap
  25099. if (json.wireframeLinejoin !== undefined) material.wireframeLinejoin = json.wireframeLinejoin
  25100. if (json.rotation !== undefined) material.rotation = json.rotation
  25101. if (json.linewidth !== 1) material.linewidth = json.linewidth
  25102. if (json.dashSize !== undefined) material.dashSize = json.dashSize
  25103. if (json.gapSize !== undefined) material.gapSize = json.gapSize
  25104. if (json.scale !== undefined) material.scale = json.scale
  25105. if (json.polygonOffset !== undefined) material.polygonOffset = json.polygonOffset
  25106. if (json.polygonOffsetFactor !== undefined) material.polygonOffsetFactor = json.polygonOffsetFactor
  25107. if (json.polygonOffsetUnits !== undefined) material.polygonOffsetUnits = json.polygonOffsetUnits
  25108. if (json.dithering !== undefined) material.dithering = json.dithering
  25109. if (json.alphaToCoverage !== undefined) material.alphaToCoverage = json.alphaToCoverage
  25110. if (json.premultipliedAlpha !== undefined) material.premultipliedAlpha = json.premultipliedAlpha
  25111. if (json.visible !== undefined) material.visible = json.visible
  25112. if (json.toneMapped !== undefined) material.toneMapped = json.toneMapped
  25113. if (json.userData !== undefined) material.userData = json.userData
  25114. if (json.vertexColors !== undefined) {
  25115. if (typeof json.vertexColors === 'number') {
  25116. material.vertexColors = json.vertexColors > 0 ? true : false
  25117. } else {
  25118. material.vertexColors = json.vertexColors
  25119. }
  25120. }
  25121. // Shader Material
  25122. if (json.uniforms !== undefined) {
  25123. for (const name in json.uniforms) {
  25124. const uniform = json.uniforms[name]
  25125. material.uniforms[name] = {}
  25126. switch (uniform.type) {
  25127. case 't':
  25128. material.uniforms[name].value = getTexture(uniform.value)
  25129. break
  25130. case 'c':
  25131. material.uniforms[name].value = new Color().setHex(uniform.value)
  25132. break
  25133. case 'v2':
  25134. material.uniforms[name].value = new Vector2().fromArray(uniform.value)
  25135. break
  25136. case 'v3':
  25137. material.uniforms[name].value = new Vector3().fromArray(uniform.value)
  25138. break
  25139. case 'v4':
  25140. material.uniforms[name].value = new Vector4().fromArray(uniform.value)
  25141. break
  25142. case 'm3':
  25143. material.uniforms[name].value = new Matrix3().fromArray(uniform.value)
  25144. break
  25145. case 'm4':
  25146. material.uniforms[name].value = new Matrix4().fromArray(uniform.value)
  25147. break
  25148. default:
  25149. material.uniforms[name].value = uniform.value
  25150. }
  25151. }
  25152. }
  25153. if (json.defines !== undefined) material.defines = json.defines
  25154. if (json.vertexShader !== undefined) material.vertexShader = json.vertexShader
  25155. if (json.fragmentShader !== undefined) material.fragmentShader = json.fragmentShader
  25156. if (json.extensions !== undefined) {
  25157. for (const key in json.extensions) {
  25158. material.extensions[key] = json.extensions[key]
  25159. }
  25160. }
  25161. // Deprecated
  25162. if (json.shading !== undefined) material.flatShading = json.shading === 1 // THREE.FlatShading
  25163. // for PointsMaterial
  25164. if (json.size !== undefined) material.size = json.size
  25165. if (json.sizeAttenuation !== undefined) material.sizeAttenuation = json.sizeAttenuation
  25166. // maps
  25167. if (json.map !== undefined) material.map = getTexture(json.map)
  25168. if (json.matcap !== undefined) material.matcap = getTexture(json.matcap)
  25169. if (json.alphaMap !== undefined) material.alphaMap = getTexture(json.alphaMap)
  25170. if (json.bumpMap !== undefined) material.bumpMap = getTexture(json.bumpMap)
  25171. if (json.bumpScale !== undefined) material.bumpScale = json.bumpScale
  25172. if (json.normalMap !== undefined) material.normalMap = getTexture(json.normalMap)
  25173. if (json.normalMapType !== undefined) material.normalMapType = json.normalMapType
  25174. if (json.normalScale !== undefined) {
  25175. let normalScale = json.normalScale
  25176. if (Array.isArray(normalScale) === false) {
  25177. // Blender exporter used to export a scalar. See #7459
  25178. normalScale = [normalScale, normalScale]
  25179. }
  25180. material.normalScale = new Vector2().fromArray(normalScale)
  25181. }
  25182. if (json.displacementMap !== undefined) material.displacementMap = getTexture(json.displacementMap)
  25183. if (json.displacementScale !== undefined) material.displacementScale = json.displacementScale
  25184. if (json.displacementBias !== undefined) material.displacementBias = json.displacementBias
  25185. if (json.roughnessMap !== undefined) material.roughnessMap = getTexture(json.roughnessMap)
  25186. if (json.metalnessMap !== undefined) material.metalnessMap = getTexture(json.metalnessMap)
  25187. if (json.emissiveMap !== undefined) material.emissiveMap = getTexture(json.emissiveMap)
  25188. if (json.emissiveIntensity !== undefined) material.emissiveIntensity = json.emissiveIntensity
  25189. if (json.specularMap !== undefined) material.specularMap = getTexture(json.specularMap)
  25190. if (json.specularIntensityMap !== undefined) material.specularIntensityMap = getTexture(json.specularIntensityMap)
  25191. if (json.specularColorMap !== undefined) material.specularColorMap = getTexture(json.specularColorMap)
  25192. if (json.envMap !== undefined) material.envMap = getTexture(json.envMap)
  25193. if (json.envMapIntensity !== undefined) material.envMapIntensity = json.envMapIntensity
  25194. if (json.reflectivity !== undefined) material.reflectivity = json.reflectivity
  25195. if (json.refractionRatio !== undefined) material.refractionRatio = json.refractionRatio
  25196. if (json.lightMap !== undefined) material.lightMap = getTexture(json.lightMap)
  25197. if (json.lightMapIntensity !== undefined) material.lightMapIntensity = json.lightMapIntensity
  25198. if (json.aoMap !== undefined) material.aoMap = getTexture(json.aoMap)
  25199. if (json.aoMapIntensity !== undefined) material.aoMapIntensity = json.aoMapIntensity
  25200. if (json.gradientMap !== undefined) material.gradientMap = getTexture(json.gradientMap)
  25201. if (json.clearcoatMap !== undefined) material.clearcoatMap = getTexture(json.clearcoatMap)
  25202. if (json.clearcoatRoughnessMap !== undefined) material.clearcoatRoughnessMap = getTexture(json.clearcoatRoughnessMap)
  25203. if (json.clearcoatNormalMap !== undefined) material.clearcoatNormalMap = getTexture(json.clearcoatNormalMap)
  25204. if (json.clearcoatNormalScale !== undefined) material.clearcoatNormalScale = new Vector2().fromArray(json.clearcoatNormalScale)
  25205. if (json.iridescenceMap !== undefined) material.iridescenceMap = getTexture(json.iridescenceMap)
  25206. if (json.iridescenceThicknessMap !== undefined) material.iridescenceThicknessMap = getTexture(json.iridescenceThicknessMap)
  25207. if (json.transmissionMap !== undefined) material.transmissionMap = getTexture(json.transmissionMap)
  25208. if (json.thicknessMap !== undefined) material.thicknessMap = getTexture(json.thicknessMap)
  25209. if (json.sheenColorMap !== undefined) material.sheenColorMap = getTexture(json.sheenColorMap)
  25210. if (json.sheenRoughnessMap !== undefined) material.sheenRoughnessMap = getTexture(json.sheenRoughnessMap)
  25211. return material
  25212. }
  25213. setTextures(value) {
  25214. this.textures = value
  25215. return this
  25216. }
  25217. }
  25218. class LoaderUtils {
  25219. static decodeText(array) {
  25220. if (typeof TextDecoder !== 'undefined') {
  25221. return new TextDecoder().decode(array)
  25222. }
  25223. // Avoid the String.fromCharCode.apply(null, array) shortcut, which
  25224. // throws a "maximum call stack size exceeded" error for large arrays.
  25225. let s = ''
  25226. for (let i = 0, il = array.length; i < il; i++) {
  25227. // Implicitly assumes little-endian.
  25228. s += String.fromCharCode(array[i])
  25229. }
  25230. try {
  25231. // merges multi-byte utf-8 characters.
  25232. return decodeURIComponent(escape(s))
  25233. } catch (e) {
  25234. // see #16358
  25235. return s
  25236. }
  25237. }
  25238. static extractUrlBase(url) {
  25239. const index = url.lastIndexOf('/')
  25240. if (index === -1) return './'
  25241. return url.slice(0, index + 1)
  25242. }
  25243. static resolveURL(url, path) {
  25244. // Invalid URL
  25245. if (typeof url !== 'string' || url === '') return ''
  25246. // Host Relative URL
  25247. if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
  25248. path = path.replace(/(^https?:\/\/[^\/]+).*/i, '$1')
  25249. }
  25250. // Absolute URL http://,https://,//
  25251. if (/^(https?:)?\/\//i.test(url)) return url
  25252. // Data URI
  25253. if (/^data:.*,.*$/i.test(url)) return url
  25254. // Blob URL
  25255. if (/^blob:.*$/i.test(url)) return url
  25256. // Relative URL
  25257. return path + url
  25258. }
  25259. }
  25260. class InstancedBufferGeometry extends BufferGeometry {
  25261. constructor() {
  25262. super()
  25263. this.isInstancedBufferGeometry = true
  25264. this.type = 'InstancedBufferGeometry'
  25265. this.instanceCount = Infinity
  25266. }
  25267. copy(source) {
  25268. super.copy(source)
  25269. this.instanceCount = source.instanceCount
  25270. return this
  25271. }
  25272. clone() {
  25273. return new this.constructor().copy(this)
  25274. }
  25275. toJSON() {
  25276. const data = super.toJSON(this)
  25277. data.instanceCount = this.instanceCount
  25278. data.isInstancedBufferGeometry = true
  25279. return data
  25280. }
  25281. }
  25282. class BufferGeometryLoader extends Loader {
  25283. constructor(manager) {
  25284. super(manager)
  25285. }
  25286. load(url, onLoad, onProgress, onError) {
  25287. const scope = this
  25288. const loader = new FileLoader(scope.manager)
  25289. loader.setPath(scope.path)
  25290. loader.setRequestHeader(scope.requestHeader)
  25291. loader.setWithCredentials(scope.withCredentials)
  25292. loader.load(
  25293. url,
  25294. function(text) {
  25295. try {
  25296. onLoad(scope.parse(JSON.parse(text)))
  25297. } catch (e) {
  25298. if (onError) {
  25299. onError(e)
  25300. } else {
  25301. console.error(e)
  25302. }
  25303. scope.manager.itemError(url)
  25304. }
  25305. },
  25306. onProgress,
  25307. onError
  25308. )
  25309. }
  25310. parse(json) {
  25311. const interleavedBufferMap = {}
  25312. const arrayBufferMap = {}
  25313. function getInterleavedBuffer(json, uuid) {
  25314. if (interleavedBufferMap[uuid] !== undefined) return interleavedBufferMap[uuid]
  25315. const interleavedBuffers = json.interleavedBuffers
  25316. const interleavedBuffer = interleavedBuffers[uuid]
  25317. const buffer = getArrayBuffer(json, interleavedBuffer.buffer)
  25318. const array = getTypedArray(interleavedBuffer.type, buffer)
  25319. const ib = new InterleavedBuffer(array, interleavedBuffer.stride)
  25320. ib.uuid = interleavedBuffer.uuid
  25321. interleavedBufferMap[uuid] = ib
  25322. return ib
  25323. }
  25324. function getArrayBuffer(json, uuid) {
  25325. if (arrayBufferMap[uuid] !== undefined) return arrayBufferMap[uuid]
  25326. const arrayBuffers = json.arrayBuffers
  25327. const arrayBuffer = arrayBuffers[uuid]
  25328. const ab = new Uint32Array(arrayBuffer).buffer
  25329. arrayBufferMap[uuid] = ab
  25330. return ab
  25331. }
  25332. const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry()
  25333. const index = json.data.index
  25334. if (index !== undefined) {
  25335. const typedArray = getTypedArray(index.type, index.array)
  25336. geometry.setIndex(new BufferAttribute(typedArray, 1))
  25337. }
  25338. const attributes = json.data.attributes
  25339. for (const key in attributes) {
  25340. const attribute = attributes[key]
  25341. let bufferAttribute
  25342. if (attribute.isInterleavedBufferAttribute) {
  25343. const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data)
  25344. bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized)
  25345. } else {
  25346. const typedArray = getTypedArray(attribute.type, attribute.array)
  25347. const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute
  25348. bufferAttribute = new bufferAttributeConstr(typedArray, attribute.itemSize, attribute.normalized)
  25349. }
  25350. if (attribute.name !== undefined) bufferAttribute.name = attribute.name
  25351. if (attribute.usage !== undefined) bufferAttribute.setUsage(attribute.usage)
  25352. if (attribute.updateRange !== undefined) {
  25353. bufferAttribute.updateRange.offset = attribute.updateRange.offset
  25354. bufferAttribute.updateRange.count = attribute.updateRange.count
  25355. }
  25356. geometry.setAttribute(key, bufferAttribute)
  25357. }
  25358. const morphAttributes = json.data.morphAttributes
  25359. if (morphAttributes) {
  25360. for (const key in morphAttributes) {
  25361. const attributeArray = morphAttributes[key]
  25362. const array = []
  25363. for (let i = 0, il = attributeArray.length; i < il; i++) {
  25364. const attribute = attributeArray[i]
  25365. let bufferAttribute
  25366. if (attribute.isInterleavedBufferAttribute) {
  25367. const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data)
  25368. bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized)
  25369. } else {
  25370. const typedArray = getTypedArray(attribute.type, attribute.array)
  25371. bufferAttribute = new BufferAttribute(typedArray, attribute.itemSize, attribute.normalized)
  25372. }
  25373. if (attribute.name !== undefined) bufferAttribute.name = attribute.name
  25374. array.push(bufferAttribute)
  25375. }
  25376. geometry.morphAttributes[key] = array
  25377. }
  25378. }
  25379. const morphTargetsRelative = json.data.morphTargetsRelative
  25380. if (morphTargetsRelative) {
  25381. geometry.morphTargetsRelative = true
  25382. }
  25383. const groups = json.data.groups || json.data.drawcalls || json.data.offsets
  25384. if (groups !== undefined) {
  25385. for (let i = 0, n = groups.length; i !== n; ++i) {
  25386. const group = groups[i]
  25387. geometry.addGroup(group.start, group.count, group.materialIndex)
  25388. }
  25389. }
  25390. const boundingSphere = json.data.boundingSphere
  25391. if (boundingSphere !== undefined) {
  25392. const center = new Vector3()
  25393. if (boundingSphere.center !== undefined) {
  25394. center.fromArray(boundingSphere.center)
  25395. }
  25396. geometry.boundingSphere = new Sphere(center, boundingSphere.radius)
  25397. }
  25398. if (json.name) geometry.name = json.name
  25399. if (json.userData) geometry.userData = json.userData
  25400. return geometry
  25401. }
  25402. }
  25403. class ObjectLoader extends Loader {
  25404. constructor(manager) {
  25405. super(manager)
  25406. }
  25407. load(url, onLoad, onProgress, onError) {
  25408. const scope = this
  25409. const path = this.path === '' ? LoaderUtils.extractUrlBase(url) : this.path
  25410. this.resourcePath = this.resourcePath || path
  25411. const loader = new FileLoader(this.manager)
  25412. loader.setPath(this.path)
  25413. loader.setRequestHeader(this.requestHeader)
  25414. loader.setWithCredentials(this.withCredentials)
  25415. loader.load(
  25416. url,
  25417. function(text) {
  25418. let json = null
  25419. try {
  25420. json = JSON.parse(text)
  25421. } catch (error) {
  25422. if (onError !== undefined) onError(error)
  25423. console.error("THREE:ObjectLoader: Can't parse " + url + '.', error.message)
  25424. return
  25425. }
  25426. const metadata = json.metadata
  25427. if (metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry') {
  25428. console.error("THREE.ObjectLoader: Can't load " + url)
  25429. return
  25430. }
  25431. scope.parse(json, onLoad)
  25432. },
  25433. onProgress,
  25434. onError
  25435. )
  25436. }
  25437. async loadAsync(url, onProgress) {
  25438. const scope = this
  25439. const path = this.path === '' ? LoaderUtils.extractUrlBase(url) : this.path
  25440. this.resourcePath = this.resourcePath || path
  25441. const loader = new FileLoader(this.manager)
  25442. loader.setPath(this.path)
  25443. loader.setRequestHeader(this.requestHeader)
  25444. loader.setWithCredentials(this.withCredentials)
  25445. const text = await loader.loadAsync(url, onProgress)
  25446. const json = JSON.parse(text)
  25447. const metadata = json.metadata
  25448. if (metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry') {
  25449. throw new Error("THREE.ObjectLoader: Can't load " + url)
  25450. }
  25451. return await scope.parseAsync(json)
  25452. }
  25453. parse(json, onLoad) {
  25454. const animations = this.parseAnimations(json.animations)
  25455. const shapes = this.parseShapes(json.shapes)
  25456. const geometries = this.parseGeometries(json.geometries, shapes)
  25457. const images = this.parseImages(json.images, function() {
  25458. if (onLoad !== undefined) onLoad(object)
  25459. })
  25460. const textures = this.parseTextures(json.textures, images)
  25461. const materials = this.parseMaterials(json.materials, textures)
  25462. const object = this.parseObject(json.object, geometries, materials, textures, animations)
  25463. const skeletons = this.parseSkeletons(json.skeletons, object)
  25464. this.bindSkeletons(object, skeletons)
  25465. //
  25466. if (onLoad !== undefined) {
  25467. let hasImages = false
  25468. for (const uuid in images) {
  25469. if (images[uuid].data instanceof HTMLImageElement) {
  25470. hasImages = true
  25471. break
  25472. }
  25473. }
  25474. if (hasImages === false) onLoad(object)
  25475. }
  25476. return object
  25477. }
  25478. async parseAsync(json) {
  25479. const animations = this.parseAnimations(json.animations)
  25480. const shapes = this.parseShapes(json.shapes)
  25481. const geometries = this.parseGeometries(json.geometries, shapes)
  25482. const images = await this.parseImagesAsync(json.images)
  25483. const textures = this.parseTextures(json.textures, images)
  25484. const materials = this.parseMaterials(json.materials, textures)
  25485. const object = this.parseObject(json.object, geometries, materials, textures, animations)
  25486. const skeletons = this.parseSkeletons(json.skeletons, object)
  25487. this.bindSkeletons(object, skeletons)
  25488. return object
  25489. }
  25490. parseShapes(json) {
  25491. const shapes = {}
  25492. if (json !== undefined) {
  25493. for (let i = 0, l = json.length; i < l; i++) {
  25494. const shape = new Shape().fromJSON(json[i])
  25495. shapes[shape.uuid] = shape
  25496. }
  25497. }
  25498. return shapes
  25499. }
  25500. parseSkeletons(json, object) {
  25501. const skeletons = {}
  25502. const bones = {}
  25503. // generate bone lookup table
  25504. object.traverse(function(child) {
  25505. if (child.isBone) bones[child.uuid] = child
  25506. })
  25507. // create skeletons
  25508. if (json !== undefined) {
  25509. for (let i = 0, l = json.length; i < l; i++) {
  25510. const skeleton = new Skeleton().fromJSON(json[i], bones)
  25511. skeletons[skeleton.uuid] = skeleton
  25512. }
  25513. }
  25514. return skeletons
  25515. }
  25516. parseGeometries(json, shapes) {
  25517. const geometries = {}
  25518. if (json !== undefined) {
  25519. const bufferGeometryLoader = new BufferGeometryLoader()
  25520. for (let i = 0, l = json.length; i < l; i++) {
  25521. let geometry
  25522. const data = json[i]
  25523. switch (data.type) {
  25524. case 'BufferGeometry':
  25525. case 'InstancedBufferGeometry':
  25526. geometry = bufferGeometryLoader.parse(data)
  25527. break
  25528. case 'Geometry':
  25529. console.error('THREE.ObjectLoader: The legacy Geometry type is no longer supported.')
  25530. break
  25531. default:
  25532. if (data.type in Geometries) {
  25533. geometry = Geometries[data.type].fromJSON(data, shapes)
  25534. } else {
  25535. console.warn(`THREE.ObjectLoader: Unsupported geometry type "${data.type}"`)
  25536. }
  25537. }
  25538. geometry.uuid = data.uuid
  25539. if (data.name !== undefined) geometry.name = data.name
  25540. if (geometry.isBufferGeometry === true && data.userData !== undefined) geometry.userData = data.userData
  25541. geometries[data.uuid] = geometry
  25542. }
  25543. }
  25544. return geometries
  25545. }
  25546. parseMaterials(json, textures) {
  25547. const cache = {} // MultiMaterial
  25548. const materials = {}
  25549. if (json !== undefined) {
  25550. const loader = new MaterialLoader()
  25551. loader.setTextures(textures)
  25552. for (let i = 0, l = json.length; i < l; i++) {
  25553. const data = json[i]
  25554. if (data.type === 'MultiMaterial') {
  25555. // Deprecated
  25556. const array = []
  25557. for (let j = 0; j < data.materials.length; j++) {
  25558. const material = data.materials[j]
  25559. if (cache[material.uuid] === undefined) {
  25560. cache[material.uuid] = loader.parse(material)
  25561. }
  25562. array.push(cache[material.uuid])
  25563. }
  25564. materials[data.uuid] = array
  25565. } else {
  25566. if (cache[data.uuid] === undefined) {
  25567. cache[data.uuid] = loader.parse(data)
  25568. }
  25569. materials[data.uuid] = cache[data.uuid]
  25570. }
  25571. }
  25572. }
  25573. return materials
  25574. }
  25575. parseAnimations(json) {
  25576. const animations = {}
  25577. if (json !== undefined) {
  25578. for (let i = 0; i < json.length; i++) {
  25579. const data = json[i]
  25580. const clip = AnimationClip.parse(data)
  25581. animations[clip.uuid] = clip
  25582. }
  25583. }
  25584. return animations
  25585. }
  25586. parseImages(json, onLoad) {
  25587. const scope = this
  25588. const images = {}
  25589. let loader
  25590. function loadImage(url) {
  25591. scope.manager.itemStart(url)
  25592. return loader.load(
  25593. url,
  25594. function() {
  25595. scope.manager.itemEnd(url)
  25596. },
  25597. undefined,
  25598. function() {
  25599. scope.manager.itemError(url)
  25600. scope.manager.itemEnd(url)
  25601. }
  25602. )
  25603. }
  25604. function deserializeImage(image) {
  25605. if (typeof image === 'string') {
  25606. const url = image
  25607. const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url
  25608. return loadImage(path)
  25609. } else {
  25610. if (image.data) {
  25611. return {
  25612. data: getTypedArray(image.type, image.data),
  25613. width: image.width,
  25614. height: image.height
  25615. }
  25616. } else {
  25617. return null
  25618. }
  25619. }
  25620. }
  25621. if (json !== undefined && json.length > 0) {
  25622. const manager = new LoadingManager(onLoad)
  25623. loader = new ImageLoader(manager)
  25624. loader.setCrossOrigin(this.crossOrigin)
  25625. for (let i = 0, il = json.length; i < il; i++) {
  25626. const image = json[i]
  25627. const url = image.url
  25628. if (Array.isArray(url)) {
  25629. // load array of images e.g CubeTexture
  25630. const imageArray = []
  25631. for (let j = 0, jl = url.length; j < jl; j++) {
  25632. const currentUrl = url[j]
  25633. const deserializedImage = deserializeImage(currentUrl)
  25634. if (deserializedImage !== null) {
  25635. if (deserializedImage instanceof HTMLImageElement) {
  25636. imageArray.push(deserializedImage)
  25637. } else {
  25638. // special case: handle array of data textures for cube textures
  25639. imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height))
  25640. }
  25641. }
  25642. }
  25643. images[image.uuid] = new Source(imageArray)
  25644. } else {
  25645. // load single image
  25646. const deserializedImage = deserializeImage(image.url)
  25647. images[image.uuid] = new Source(deserializedImage)
  25648. }
  25649. }
  25650. }
  25651. return images
  25652. }
  25653. async parseImagesAsync(json) {
  25654. const scope = this
  25655. const images = {}
  25656. let loader
  25657. async function deserializeImage(image) {
  25658. if (typeof image === 'string') {
  25659. const url = image
  25660. const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url
  25661. return await loader.loadAsync(path)
  25662. } else {
  25663. if (image.data) {
  25664. return {
  25665. data: getTypedArray(image.type, image.data),
  25666. width: image.width,
  25667. height: image.height
  25668. }
  25669. } else {
  25670. return null
  25671. }
  25672. }
  25673. }
  25674. if (json !== undefined && json.length > 0) {
  25675. loader = new ImageLoader(this.manager)
  25676. loader.setCrossOrigin(this.crossOrigin)
  25677. for (let i = 0, il = json.length; i < il; i++) {
  25678. const image = json[i]
  25679. const url = image.url
  25680. if (Array.isArray(url)) {
  25681. // load array of images e.g CubeTexture
  25682. const imageArray = []
  25683. for (let j = 0, jl = url.length; j < jl; j++) {
  25684. const currentUrl = url[j]
  25685. const deserializedImage = await deserializeImage(currentUrl)
  25686. if (deserializedImage !== null) {
  25687. if (deserializedImage instanceof HTMLImageElement) {
  25688. imageArray.push(deserializedImage)
  25689. } else {
  25690. // special case: handle array of data textures for cube textures
  25691. imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height))
  25692. }
  25693. }
  25694. }
  25695. images[image.uuid] = new Source(imageArray)
  25696. } else {
  25697. // load single image
  25698. const deserializedImage = await deserializeImage(image.url)
  25699. images[image.uuid] = new Source(deserializedImage)
  25700. }
  25701. }
  25702. }
  25703. return images
  25704. }
  25705. parseTextures(json, images) {
  25706. function parseConstant(value, type) {
  25707. if (typeof value === 'number') return value
  25708. console.warn('THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value)
  25709. return type[value]
  25710. }
  25711. const textures = {}
  25712. if (json !== undefined) {
  25713. for (let i = 0, l = json.length; i < l; i++) {
  25714. const data = json[i]
  25715. if (data.image === undefined) {
  25716. console.warn('THREE.ObjectLoader: No "image" specified for', data.uuid)
  25717. }
  25718. if (images[data.image] === undefined) {
  25719. console.warn('THREE.ObjectLoader: Undefined image', data.image)
  25720. }
  25721. const source = images[data.image]
  25722. const image = source.data
  25723. let texture
  25724. if (Array.isArray(image)) {
  25725. texture = new CubeTexture()
  25726. if (image.length === 6) texture.needsUpdate = true
  25727. } else {
  25728. if (image && image.data) {
  25729. texture = new DataTexture()
  25730. } else {
  25731. texture = new Texture()
  25732. }
  25733. if (image) texture.needsUpdate = true // textures can have undefined image data
  25734. }
  25735. texture.source = source
  25736. texture.uuid = data.uuid
  25737. if (data.name !== undefined) texture.name = data.name
  25738. if (data.mapping !== undefined) texture.mapping = parseConstant(data.mapping, TEXTURE_MAPPING)
  25739. if (data.offset !== undefined) texture.offset.fromArray(data.offset)
  25740. if (data.repeat !== undefined) texture.repeat.fromArray(data.repeat)
  25741. if (data.center !== undefined) texture.center.fromArray(data.center)
  25742. if (data.rotation !== undefined) texture.rotation = data.rotation
  25743. if (data.wrap !== undefined) {
  25744. texture.wrapS = parseConstant(data.wrap[0], TEXTURE_WRAPPING)
  25745. texture.wrapT = parseConstant(data.wrap[1], TEXTURE_WRAPPING)
  25746. }
  25747. if (data.format !== undefined) texture.format = data.format
  25748. if (data.type !== undefined) texture.type = data.type
  25749. if (data.encoding !== undefined) texture.encoding = data.encoding
  25750. if (data.minFilter !== undefined) texture.minFilter = parseConstant(data.minFilter, TEXTURE_FILTER)
  25751. if (data.magFilter !== undefined) texture.magFilter = parseConstant(data.magFilter, TEXTURE_FILTER)
  25752. if (data.anisotropy !== undefined) texture.anisotropy = data.anisotropy
  25753. if (data.flipY !== undefined) texture.flipY = data.flipY
  25754. if (data.premultiplyAlpha !== undefined) texture.premultiplyAlpha = data.premultiplyAlpha
  25755. if (data.unpackAlignment !== undefined) texture.unpackAlignment = data.unpackAlignment
  25756. if (data.userData !== undefined) texture.userData = data.userData
  25757. textures[data.uuid] = texture
  25758. }
  25759. }
  25760. return textures
  25761. }
  25762. parseObject(data, geometries, materials, textures, animations) {
  25763. let object
  25764. function getGeometry(name) {
  25765. if (geometries[name] === undefined) {
  25766. console.warn('THREE.ObjectLoader: Undefined geometry', name)
  25767. }
  25768. return geometries[name]
  25769. }
  25770. function getMaterial(name) {
  25771. if (name === undefined) return undefined
  25772. if (Array.isArray(name)) {
  25773. const array = []
  25774. for (let i = 0, l = name.length; i < l; i++) {
  25775. const uuid = name[i]
  25776. if (materials[uuid] === undefined) {
  25777. console.warn('THREE.ObjectLoader: Undefined material', uuid)
  25778. }
  25779. array.push(materials[uuid])
  25780. }
  25781. return array
  25782. }
  25783. if (materials[name] === undefined) {
  25784. console.warn('THREE.ObjectLoader: Undefined material', name)
  25785. }
  25786. return materials[name]
  25787. }
  25788. function getTexture(uuid) {
  25789. if (textures[uuid] === undefined) {
  25790. console.warn('THREE.ObjectLoader: Undefined texture', uuid)
  25791. }
  25792. return textures[uuid]
  25793. }
  25794. let geometry, material
  25795. switch (data.type) {
  25796. case 'Scene':
  25797. object = new Scene()
  25798. if (data.background !== undefined) {
  25799. if (Number.isInteger(data.background)) {
  25800. object.background = new Color(data.background)
  25801. } else {
  25802. object.background = getTexture(data.background)
  25803. }
  25804. }
  25805. if (data.environment !== undefined) {
  25806. object.environment = getTexture(data.environment)
  25807. }
  25808. if (data.fog !== undefined) {
  25809. if (data.fog.type === 'Fog') {
  25810. object.fog = new Fog(data.fog.color, data.fog.near, data.fog.far)
  25811. } else if (data.fog.type === 'FogExp2') {
  25812. object.fog = new FogExp2(data.fog.color, data.fog.density)
  25813. }
  25814. }
  25815. break
  25816. case 'PerspectiveCamera':
  25817. object = new PerspectiveCamera(data.fov, data.aspect, data.near, data.far)
  25818. if (data.focus !== undefined) object.focus = data.focus
  25819. if (data.zoom !== undefined) object.zoom = data.zoom
  25820. if (data.filmGauge !== undefined) object.filmGauge = data.filmGauge
  25821. if (data.filmOffset !== undefined) object.filmOffset = data.filmOffset
  25822. if (data.view !== undefined) object.view = Object.assign({}, data.view)
  25823. break
  25824. case 'OrthographicCamera':
  25825. object = new OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far)
  25826. if (data.zoom !== undefined) object.zoom = data.zoom
  25827. if (data.view !== undefined) object.view = Object.assign({}, data.view)
  25828. break
  25829. case 'AmbientLight':
  25830. object = new AmbientLight(data.color, data.intensity)
  25831. break
  25832. case 'DirectionalLight':
  25833. object = new DirectionalLight(data.color, data.intensity)
  25834. break
  25835. case 'PointLight':
  25836. object = new PointLight(data.color, data.intensity, data.distance, data.decay)
  25837. break
  25838. case 'RectAreaLight':
  25839. object = new RectAreaLight(data.color, data.intensity, data.width, data.height)
  25840. break
  25841. case 'SpotLight':
  25842. object = new SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay)
  25843. break
  25844. case 'HemisphereLight':
  25845. object = new HemisphereLight(data.color, data.groundColor, data.intensity)
  25846. break
  25847. case 'LightProbe':
  25848. object = new LightProbe().fromJSON(data)
  25849. break
  25850. case 'SkinnedMesh':
  25851. geometry = getGeometry(data.geometry)
  25852. material = getMaterial(data.material)
  25853. object = new SkinnedMesh(geometry, material)
  25854. if (data.bindMode !== undefined) object.bindMode = data.bindMode
  25855. if (data.bindMatrix !== undefined) object.bindMatrix.fromArray(data.bindMatrix)
  25856. if (data.skeleton !== undefined) object.skeleton = data.skeleton
  25857. break
  25858. case 'Mesh':
  25859. geometry = getGeometry(data.geometry)
  25860. material = getMaterial(data.material)
  25861. object = new Mesh(geometry, material)
  25862. break
  25863. case 'InstancedMesh':
  25864. geometry = getGeometry(data.geometry)
  25865. material = getMaterial(data.material)
  25866. const count = data.count
  25867. const instanceMatrix = data.instanceMatrix
  25868. const instanceColor = data.instanceColor
  25869. object = new InstancedMesh(geometry, material, count)
  25870. object.instanceMatrix = new InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16)
  25871. if (instanceColor !== undefined) object.instanceColor = new InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize)
  25872. break
  25873. case 'LOD':
  25874. object = new LOD()
  25875. break
  25876. case 'Line':
  25877. object = new Line(getGeometry(data.geometry), getMaterial(data.material))
  25878. break
  25879. case 'LineLoop':
  25880. object = new LineLoop(getGeometry(data.geometry), getMaterial(data.material))
  25881. break
  25882. case 'LineSegments':
  25883. object = new LineSegments(getGeometry(data.geometry), getMaterial(data.material))
  25884. break
  25885. case 'PointCloud':
  25886. case 'Points':
  25887. object = new Points(getGeometry(data.geometry), getMaterial(data.material))
  25888. break
  25889. case 'Sprite':
  25890. object = new Sprite(getMaterial(data.material))
  25891. break
  25892. case 'Group':
  25893. object = new Group()
  25894. break
  25895. case 'Bone':
  25896. object = new Bone()
  25897. break
  25898. default:
  25899. object = new Object3D()
  25900. }
  25901. object.uuid = data.uuid
  25902. if (data.name !== undefined) object.name = data.name
  25903. if (data.matrix !== undefined) {
  25904. object.matrix.fromArray(data.matrix)
  25905. if (data.matrixAutoUpdate !== undefined) object.matrixAutoUpdate = data.matrixAutoUpdate
  25906. if (object.matrixAutoUpdate) object.matrix.decompose(object.position, object.quaternion, object.scale)
  25907. } else {
  25908. if (data.position !== undefined) object.position.fromArray(data.position)
  25909. if (data.rotation !== undefined) object.rotation.fromArray(data.rotation)
  25910. if (data.quaternion !== undefined) object.quaternion.fromArray(data.quaternion)
  25911. if (data.scale !== undefined) object.scale.fromArray(data.scale)
  25912. }
  25913. if (data.castShadow !== undefined) object.castShadow = data.castShadow
  25914. if (data.receiveShadow !== undefined) object.receiveShadow = data.receiveShadow
  25915. if (data.shadow) {
  25916. if (data.shadow.bias !== undefined) object.shadow.bias = data.shadow.bias
  25917. if (data.shadow.normalBias !== undefined) object.shadow.normalBias = data.shadow.normalBias
  25918. if (data.shadow.radius !== undefined) object.shadow.radius = data.shadow.radius
  25919. if (data.shadow.mapSize !== undefined) object.shadow.mapSize.fromArray(data.shadow.mapSize)
  25920. if (data.shadow.camera !== undefined) object.shadow.camera = this.parseObject(data.shadow.camera)
  25921. }
  25922. if (data.visible !== undefined) object.visible = data.visible
  25923. if (data.frustumCulled !== undefined) object.frustumCulled = data.frustumCulled
  25924. if (data.renderOrder !== undefined) object.renderOrder = data.renderOrder
  25925. if (data.userData !== undefined) object.userData = data.userData
  25926. if (data.layers !== undefined) object.layers.mask = data.layers
  25927. if (data.children !== undefined) {
  25928. const children = data.children
  25929. for (let i = 0; i < children.length; i++) {
  25930. object.add(this.parseObject(children[i], geometries, materials, textures, animations))
  25931. }
  25932. }
  25933. if (data.animations !== undefined) {
  25934. const objectAnimations = data.animations
  25935. for (let i = 0; i < objectAnimations.length; i++) {
  25936. const uuid = objectAnimations[i]
  25937. object.animations.push(animations[uuid])
  25938. }
  25939. }
  25940. if (data.type === 'LOD') {
  25941. if (data.autoUpdate !== undefined) object.autoUpdate = data.autoUpdate
  25942. const levels = data.levels
  25943. for (let l = 0; l < levels.length; l++) {
  25944. const level = levels[l]
  25945. const child = object.getObjectByProperty('uuid', level.object)
  25946. if (child !== undefined) {
  25947. object.addLevel(child, level.distance)
  25948. }
  25949. }
  25950. }
  25951. return object
  25952. }
  25953. bindSkeletons(object, skeletons) {
  25954. if (Object.keys(skeletons).length === 0) return
  25955. object.traverse(function(child) {
  25956. if (child.isSkinnedMesh === true && child.skeleton !== undefined) {
  25957. const skeleton = skeletons[child.skeleton]
  25958. if (skeleton === undefined) {
  25959. console.warn('THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton)
  25960. } else {
  25961. child.bind(skeleton, child.bindMatrix)
  25962. }
  25963. }
  25964. })
  25965. }
  25966. /* DEPRECATED */
  25967. setTexturePath(value) {
  25968. console.warn('THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().')
  25969. return this.setResourcePath(value)
  25970. }
  25971. }
  25972. const TEXTURE_MAPPING = {
  25973. UVMapping: UVMapping,
  25974. CubeReflectionMapping: CubeReflectionMapping,
  25975. CubeRefractionMapping: CubeRefractionMapping,
  25976. EquirectangularReflectionMapping: EquirectangularReflectionMapping,
  25977. EquirectangularRefractionMapping: EquirectangularRefractionMapping,
  25978. CubeUVReflectionMapping: CubeUVReflectionMapping
  25979. }
  25980. const TEXTURE_WRAPPING = {
  25981. RepeatWrapping: RepeatWrapping,
  25982. ClampToEdgeWrapping: ClampToEdgeWrapping,
  25983. MirroredRepeatWrapping: MirroredRepeatWrapping
  25984. }
  25985. const TEXTURE_FILTER = {
  25986. NearestFilter: NearestFilter,
  25987. NearestMipmapNearestFilter: NearestMipmapNearestFilter,
  25988. NearestMipmapLinearFilter: NearestMipmapLinearFilter,
  25989. LinearFilter: LinearFilter,
  25990. LinearMipmapNearestFilter: LinearMipmapNearestFilter,
  25991. LinearMipmapLinearFilter: LinearMipmapLinearFilter
  25992. }
  25993. class ImageBitmapLoader extends Loader {
  25994. constructor(manager) {
  25995. super(manager)
  25996. this.isImageBitmapLoader = true
  25997. if (typeof createImageBitmap === 'undefined') {
  25998. console.warn('THREE.ImageBitmapLoader: createImageBitmap() not supported.')
  25999. }
  26000. if (typeof fetch === 'undefined') {
  26001. console.warn('THREE.ImageBitmapLoader: fetch() not supported.')
  26002. }
  26003. this.options = { premultiplyAlpha: 'none' }
  26004. }
  26005. setOptions(options) {
  26006. this.options = options
  26007. return this
  26008. }
  26009. load(url, onLoad, onProgress, onError) {
  26010. if (url === undefined) url = ''
  26011. if (this.path !== undefined) url = this.path + url
  26012. url = this.manager.resolveURL(url)
  26013. const scope = this
  26014. const cached = Cache.get(url)
  26015. if (cached !== undefined) {
  26016. scope.manager.itemStart(url)
  26017. setTimeout(function() {
  26018. if (onLoad) onLoad(cached)
  26019. scope.manager.itemEnd(url)
  26020. }, 0)
  26021. return cached
  26022. }
  26023. const fetchOptions = {}
  26024. fetchOptions.credentials = this.crossOrigin === 'anonymous' ? 'same-origin' : 'include'
  26025. fetchOptions.headers = this.requestHeader
  26026. fetch(url, fetchOptions)
  26027. .then(function(res) {
  26028. return res.blob()
  26029. })
  26030. .then(function(blob) {
  26031. return createImageBitmap(blob, Object.assign(scope.options, { colorSpaceConversion: 'none' }))
  26032. })
  26033. .then(function(imageBitmap) {
  26034. Cache.add(url, imageBitmap)
  26035. if (onLoad) onLoad(imageBitmap)
  26036. scope.manager.itemEnd(url)
  26037. })
  26038. .catch(function(e) {
  26039. if (onError) onError(e)
  26040. scope.manager.itemError(url)
  26041. scope.manager.itemEnd(url)
  26042. })
  26043. scope.manager.itemStart(url)
  26044. }
  26045. }
  26046. let _context
  26047. const AudioContext = {
  26048. getContext: function() {
  26049. if (_context === undefined) {
  26050. _context = new (window.AudioContext || window.webkitAudioContext)()
  26051. }
  26052. return _context
  26053. },
  26054. setContext: function(value) {
  26055. _context = value
  26056. }
  26057. }
  26058. class AudioLoader extends Loader {
  26059. constructor(manager) {
  26060. super(manager)
  26061. }
  26062. load(url, onLoad, onProgress, onError) {
  26063. const scope = this
  26064. const loader = new FileLoader(this.manager)
  26065. loader.setResponseType('arraybuffer')
  26066. loader.setPath(this.path)
  26067. loader.setRequestHeader(this.requestHeader)
  26068. loader.setWithCredentials(this.withCredentials)
  26069. loader.load(
  26070. url,
  26071. function(buffer) {
  26072. try {
  26073. // Create a copy of the buffer. The `decodeAudioData` method
  26074. // detaches the buffer when complete, preventing reuse.
  26075. const bufferCopy = buffer.slice(0)
  26076. const context = AudioContext.getContext()
  26077. context.decodeAudioData(bufferCopy, function(audioBuffer) {
  26078. onLoad(audioBuffer)
  26079. })
  26080. } catch (e) {
  26081. if (onError) {
  26082. onError(e)
  26083. } else {
  26084. console.error(e)
  26085. }
  26086. scope.manager.itemError(url)
  26087. }
  26088. },
  26089. onProgress,
  26090. onError
  26091. )
  26092. }
  26093. }
  26094. class HemisphereLightProbe extends LightProbe {
  26095. constructor(skyColor, groundColor, intensity = 1) {
  26096. super(undefined, intensity)
  26097. this.isHemisphereLightProbe = true
  26098. const color1 = new Color().set(skyColor)
  26099. const color2 = new Color().set(groundColor)
  26100. const sky = new Vector3(color1.r, color1.g, color1.b)
  26101. const ground = new Vector3(color2.r, color2.g, color2.b)
  26102. // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
  26103. const c0 = Math.sqrt(Math.PI)
  26104. const c1 = c0 * Math.sqrt(0.75)
  26105. this.sh.coefficients[0]
  26106. .copy(sky)
  26107. .add(ground)
  26108. .multiplyScalar(c0)
  26109. this.sh.coefficients[1]
  26110. .copy(sky)
  26111. .sub(ground)
  26112. .multiplyScalar(c1)
  26113. }
  26114. }
  26115. class AmbientLightProbe extends LightProbe {
  26116. constructor(color, intensity = 1) {
  26117. super(undefined, intensity)
  26118. this.isAmbientLightProbe = true
  26119. const color1 = new Color().set(color)
  26120. // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
  26121. this.sh.coefficients[0].set(color1.r, color1.g, color1.b).multiplyScalar(2 * Math.sqrt(Math.PI))
  26122. }
  26123. }
  26124. const _eyeRight = /*@__PURE__*/ new Matrix4()
  26125. const _eyeLeft = /*@__PURE__*/ new Matrix4()
  26126. const _projectionMatrix = /*@__PURE__*/ new Matrix4()
  26127. class StereoCamera {
  26128. constructor() {
  26129. this.type = 'StereoCamera'
  26130. this.aspect = 1
  26131. this.eyeSep = 0.064
  26132. this.cameraL = new PerspectiveCamera()
  26133. this.cameraL.layers.enable(1)
  26134. this.cameraL.matrixAutoUpdate = false
  26135. this.cameraR = new PerspectiveCamera()
  26136. this.cameraR.layers.enable(2)
  26137. this.cameraR.matrixAutoUpdate = false
  26138. this._cache = {
  26139. focus: null,
  26140. fov: null,
  26141. aspect: null,
  26142. near: null,
  26143. far: null,
  26144. zoom: null,
  26145. eyeSep: null
  26146. }
  26147. }
  26148. update(camera) {
  26149. const cache = this._cache
  26150. const needsUpdate =
  26151. cache.focus !== camera.focus ||
  26152. cache.fov !== camera.fov ||
  26153. cache.aspect !== camera.aspect * this.aspect ||
  26154. cache.near !== camera.near ||
  26155. cache.far !== camera.far ||
  26156. cache.zoom !== camera.zoom ||
  26157. cache.eyeSep !== this.eyeSep
  26158. if (needsUpdate) {
  26159. cache.focus = camera.focus
  26160. cache.fov = camera.fov
  26161. cache.aspect = camera.aspect * this.aspect
  26162. cache.near = camera.near
  26163. cache.far = camera.far
  26164. cache.zoom = camera.zoom
  26165. cache.eyeSep = this.eyeSep
  26166. // Off-axis stereoscopic effect based on
  26167. // http://paulbourke.net/stereographics/stereorender/
  26168. _projectionMatrix.copy(camera.projectionMatrix)
  26169. const eyeSepHalf = cache.eyeSep / 2
  26170. const eyeSepOnProjection = (eyeSepHalf * cache.near) / cache.focus
  26171. const ymax = (cache.near * Math.tan(DEG2RAD * cache.fov * 0.5)) / cache.zoom
  26172. let xmin, xmax
  26173. // translate xOffset
  26174. _eyeLeft.elements[12] = -eyeSepHalf
  26175. _eyeRight.elements[12] = eyeSepHalf
  26176. // for left eye
  26177. xmin = -ymax * cache.aspect + eyeSepOnProjection
  26178. xmax = ymax * cache.aspect + eyeSepOnProjection
  26179. _projectionMatrix.elements[0] = (2 * cache.near) / (xmax - xmin)
  26180. _projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin)
  26181. this.cameraL.projectionMatrix.copy(_projectionMatrix)
  26182. // for right eye
  26183. xmin = -ymax * cache.aspect - eyeSepOnProjection
  26184. xmax = ymax * cache.aspect - eyeSepOnProjection
  26185. _projectionMatrix.elements[0] = (2 * cache.near) / (xmax - xmin)
  26186. _projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin)
  26187. this.cameraR.projectionMatrix.copy(_projectionMatrix)
  26188. }
  26189. this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(_eyeLeft)
  26190. this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(_eyeRight)
  26191. }
  26192. }
  26193. class Clock {
  26194. constructor(autoStart = true) {
  26195. this.autoStart = autoStart
  26196. this.startTime = 0
  26197. this.oldTime = 0
  26198. this.elapsedTime = 0
  26199. this.running = false
  26200. }
  26201. start() {
  26202. this.startTime = now()
  26203. this.oldTime = this.startTime
  26204. this.elapsedTime = 0
  26205. this.running = true
  26206. }
  26207. stop() {
  26208. this.getElapsedTime()
  26209. this.running = false
  26210. this.autoStart = false
  26211. }
  26212. getElapsedTime() {
  26213. this.getDelta()
  26214. return this.elapsedTime
  26215. }
  26216. getDelta() {
  26217. let diff = 0
  26218. if (this.autoStart && !this.running) {
  26219. this.start()
  26220. return 0
  26221. }
  26222. if (this.running) {
  26223. const newTime = now()
  26224. diff = (newTime - this.oldTime) / 1000
  26225. this.oldTime = newTime
  26226. this.elapsedTime += diff
  26227. }
  26228. return diff
  26229. }
  26230. }
  26231. function now() {
  26232. return (typeof performance === 'undefined' ? Date : performance).now() // see #10732
  26233. }
  26234. const _position$1 = /*@__PURE__*/ new Vector3()
  26235. const _quaternion$1 = /*@__PURE__*/ new Quaternion()
  26236. const _scale$1 = /*@__PURE__*/ new Vector3()
  26237. const _orientation$1 = /*@__PURE__*/ new Vector3()
  26238. class AudioListener extends Object3D {
  26239. constructor() {
  26240. super()
  26241. this.type = 'AudioListener'
  26242. this.context = AudioContext.getContext()
  26243. this.gain = this.context.createGain()
  26244. this.gain.connect(this.context.destination)
  26245. this.filter = null
  26246. this.timeDelta = 0
  26247. // private
  26248. this._clock = new Clock()
  26249. }
  26250. getInput() {
  26251. return this.gain
  26252. }
  26253. removeFilter() {
  26254. if (this.filter !== null) {
  26255. this.gain.disconnect(this.filter)
  26256. this.filter.disconnect(this.context.destination)
  26257. this.gain.connect(this.context.destination)
  26258. this.filter = null
  26259. }
  26260. return this
  26261. }
  26262. getFilter() {
  26263. return this.filter
  26264. }
  26265. setFilter(value) {
  26266. if (this.filter !== null) {
  26267. this.gain.disconnect(this.filter)
  26268. this.filter.disconnect(this.context.destination)
  26269. } else {
  26270. this.gain.disconnect(this.context.destination)
  26271. }
  26272. this.filter = value
  26273. this.gain.connect(this.filter)
  26274. this.filter.connect(this.context.destination)
  26275. return this
  26276. }
  26277. getMasterVolume() {
  26278. return this.gain.gain.value
  26279. }
  26280. setMasterVolume(value) {
  26281. this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01)
  26282. return this
  26283. }
  26284. updateMatrixWorld(force) {
  26285. super.updateMatrixWorld(force)
  26286. const listener = this.context.listener
  26287. const up = this.up
  26288. this.timeDelta = this._clock.getDelta()
  26289. this.matrixWorld.decompose(_position$1, _quaternion$1, _scale$1)
  26290. _orientation$1.set(0, 0, -1).applyQuaternion(_quaternion$1)
  26291. if (listener.positionX) {
  26292. // code path for Chrome (see #14393)
  26293. const endTime = this.context.currentTime + this.timeDelta
  26294. listener.positionX.linearRampToValueAtTime(_position$1.x, endTime)
  26295. listener.positionY.linearRampToValueAtTime(_position$1.y, endTime)
  26296. listener.positionZ.linearRampToValueAtTime(_position$1.z, endTime)
  26297. listener.forwardX.linearRampToValueAtTime(_orientation$1.x, endTime)
  26298. listener.forwardY.linearRampToValueAtTime(_orientation$1.y, endTime)
  26299. listener.forwardZ.linearRampToValueAtTime(_orientation$1.z, endTime)
  26300. listener.upX.linearRampToValueAtTime(up.x, endTime)
  26301. listener.upY.linearRampToValueAtTime(up.y, endTime)
  26302. listener.upZ.linearRampToValueAtTime(up.z, endTime)
  26303. } else {
  26304. listener.setPosition(_position$1.x, _position$1.y, _position$1.z)
  26305. listener.setOrientation(_orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z)
  26306. }
  26307. }
  26308. }
  26309. class Audio extends Object3D {
  26310. constructor(listener) {
  26311. super()
  26312. this.type = 'Audio'
  26313. this.listener = listener
  26314. this.context = listener.context
  26315. this.gain = this.context.createGain()
  26316. this.gain.connect(listener.getInput())
  26317. this.autoplay = false
  26318. this.buffer = null
  26319. this.detune = 0
  26320. this.loop = false
  26321. this.loopStart = 0
  26322. this.loopEnd = 0
  26323. this.offset = 0
  26324. this.duration = undefined
  26325. this.playbackRate = 1
  26326. this.isPlaying = false
  26327. this.hasPlaybackControl = true
  26328. this.source = null
  26329. this.sourceType = 'empty'
  26330. this._startedAt = 0
  26331. this._progress = 0
  26332. this._connected = false
  26333. this.filters = []
  26334. }
  26335. getOutput() {
  26336. return this.gain
  26337. }
  26338. setNodeSource(audioNode) {
  26339. this.hasPlaybackControl = false
  26340. this.sourceType = 'audioNode'
  26341. this.source = audioNode
  26342. this.connect()
  26343. return this
  26344. }
  26345. setMediaElementSource(mediaElement) {
  26346. this.hasPlaybackControl = false
  26347. this.sourceType = 'mediaNode'
  26348. this.source = this.context.createMediaElementSource(mediaElement)
  26349. this.connect()
  26350. return this
  26351. }
  26352. setMediaStreamSource(mediaStream) {
  26353. this.hasPlaybackControl = false
  26354. this.sourceType = 'mediaStreamNode'
  26355. this.source = this.context.createMediaStreamSource(mediaStream)
  26356. this.connect()
  26357. return this
  26358. }
  26359. setBuffer(audioBuffer) {
  26360. this.buffer = audioBuffer
  26361. this.sourceType = 'buffer'
  26362. if (this.autoplay) this.play()
  26363. return this
  26364. }
  26365. play(delay = 0) {
  26366. if (this.isPlaying === true) {
  26367. console.warn('THREE.Audio: Audio is already playing.')
  26368. return
  26369. }
  26370. if (this.hasPlaybackControl === false) {
  26371. console.warn('THREE.Audio: this Audio has no playback control.')
  26372. return
  26373. }
  26374. this._startedAt = this.context.currentTime + delay
  26375. const source = this.context.createBufferSource()
  26376. source.buffer = this.buffer
  26377. source.loop = this.loop
  26378. source.loopStart = this.loopStart
  26379. source.loopEnd = this.loopEnd
  26380. source.onended = this.onEnded.bind(this)
  26381. source.start(this._startedAt, this._progress + this.offset, this.duration)
  26382. this.isPlaying = true
  26383. this.source = source
  26384. this.setDetune(this.detune)
  26385. this.setPlaybackRate(this.playbackRate)
  26386. return this.connect()
  26387. }
  26388. pause() {
  26389. if (this.hasPlaybackControl === false) {
  26390. console.warn('THREE.Audio: this Audio has no playback control.')
  26391. return
  26392. }
  26393. if (this.isPlaying === true) {
  26394. // update current progress
  26395. this._progress += Math.max(this.context.currentTime - this._startedAt, 0) * this.playbackRate
  26396. if (this.loop === true) {
  26397. // ensure _progress does not exceed duration with looped audios
  26398. this._progress = this._progress % (this.duration || this.buffer.duration)
  26399. }
  26400. this.source.stop()
  26401. this.source.onended = null
  26402. this.isPlaying = false
  26403. }
  26404. return this
  26405. }
  26406. stop() {
  26407. if (this.hasPlaybackControl === false) {
  26408. console.warn('THREE.Audio: this Audio has no playback control.')
  26409. return
  26410. }
  26411. this._progress = 0
  26412. this.source.stop()
  26413. this.source.onended = null
  26414. this.isPlaying = false
  26415. return this
  26416. }
  26417. connect() {
  26418. if (this.filters.length > 0) {
  26419. this.source.connect(this.filters[0])
  26420. for (let i = 1, l = this.filters.length; i < l; i++) {
  26421. this.filters[i - 1].connect(this.filters[i])
  26422. }
  26423. this.filters[this.filters.length - 1].connect(this.getOutput())
  26424. } else {
  26425. this.source.connect(this.getOutput())
  26426. }
  26427. this._connected = true
  26428. return this
  26429. }
  26430. disconnect() {
  26431. if (this.filters.length > 0) {
  26432. this.source.disconnect(this.filters[0])
  26433. for (let i = 1, l = this.filters.length; i < l; i++) {
  26434. this.filters[i - 1].disconnect(this.filters[i])
  26435. }
  26436. this.filters[this.filters.length - 1].disconnect(this.getOutput())
  26437. } else {
  26438. this.source.disconnect(this.getOutput())
  26439. }
  26440. this._connected = false
  26441. return this
  26442. }
  26443. getFilters() {
  26444. return this.filters
  26445. }
  26446. setFilters(value) {
  26447. if (!value) value = []
  26448. if (this._connected === true) {
  26449. this.disconnect()
  26450. this.filters = value.slice()
  26451. this.connect()
  26452. } else {
  26453. this.filters = value.slice()
  26454. }
  26455. return this
  26456. }
  26457. setDetune(value) {
  26458. this.detune = value
  26459. if (this.source.detune === undefined) return // only set detune when available
  26460. if (this.isPlaying === true) {
  26461. this.source.detune.setTargetAtTime(this.detune, this.context.currentTime, 0.01)
  26462. }
  26463. return this
  26464. }
  26465. getDetune() {
  26466. return this.detune
  26467. }
  26468. getFilter() {
  26469. return this.getFilters()[0]
  26470. }
  26471. setFilter(filter) {
  26472. return this.setFilters(filter ? [filter] : [])
  26473. }
  26474. setPlaybackRate(value) {
  26475. if (this.hasPlaybackControl === false) {
  26476. console.warn('THREE.Audio: this Audio has no playback control.')
  26477. return
  26478. }
  26479. this.playbackRate = value
  26480. if (this.isPlaying === true) {
  26481. this.source.playbackRate.setTargetAtTime(this.playbackRate, this.context.currentTime, 0.01)
  26482. }
  26483. return this
  26484. }
  26485. getPlaybackRate() {
  26486. return this.playbackRate
  26487. }
  26488. onEnded() {
  26489. this.isPlaying = false
  26490. }
  26491. getLoop() {
  26492. if (this.hasPlaybackControl === false) {
  26493. console.warn('THREE.Audio: this Audio has no playback control.')
  26494. return false
  26495. }
  26496. return this.loop
  26497. }
  26498. setLoop(value) {
  26499. if (this.hasPlaybackControl === false) {
  26500. console.warn('THREE.Audio: this Audio has no playback control.')
  26501. return
  26502. }
  26503. this.loop = value
  26504. if (this.isPlaying === true) {
  26505. this.source.loop = this.loop
  26506. }
  26507. return this
  26508. }
  26509. setLoopStart(value) {
  26510. this.loopStart = value
  26511. return this
  26512. }
  26513. setLoopEnd(value) {
  26514. this.loopEnd = value
  26515. return this
  26516. }
  26517. getVolume() {
  26518. return this.gain.gain.value
  26519. }
  26520. setVolume(value) {
  26521. this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01)
  26522. return this
  26523. }
  26524. }
  26525. const _position = /*@__PURE__*/ new Vector3()
  26526. const _quaternion = /*@__PURE__*/ new Quaternion()
  26527. const _scale = /*@__PURE__*/ new Vector3()
  26528. const _orientation = /*@__PURE__*/ new Vector3()
  26529. class PositionalAudio extends Audio {
  26530. constructor(listener) {
  26531. super(listener)
  26532. this.panner = this.context.createPanner()
  26533. this.panner.panningModel = 'HRTF'
  26534. this.panner.connect(this.gain)
  26535. }
  26536. disconnect() {
  26537. super.disconnect()
  26538. this.panner.disconnect(this.gain)
  26539. }
  26540. getOutput() {
  26541. return this.panner
  26542. }
  26543. getRefDistance() {
  26544. return this.panner.refDistance
  26545. }
  26546. setRefDistance(value) {
  26547. this.panner.refDistance = value
  26548. return this
  26549. }
  26550. getRolloffFactor() {
  26551. return this.panner.rolloffFactor
  26552. }
  26553. setRolloffFactor(value) {
  26554. this.panner.rolloffFactor = value
  26555. return this
  26556. }
  26557. getDistanceModel() {
  26558. return this.panner.distanceModel
  26559. }
  26560. setDistanceModel(value) {
  26561. this.panner.distanceModel = value
  26562. return this
  26563. }
  26564. getMaxDistance() {
  26565. return this.panner.maxDistance
  26566. }
  26567. setMaxDistance(value) {
  26568. this.panner.maxDistance = value
  26569. return this
  26570. }
  26571. setDirectionalCone(coneInnerAngle, coneOuterAngle, coneOuterGain) {
  26572. this.panner.coneInnerAngle = coneInnerAngle
  26573. this.panner.coneOuterAngle = coneOuterAngle
  26574. this.panner.coneOuterGain = coneOuterGain
  26575. return this
  26576. }
  26577. updateMatrixWorld(force) {
  26578. super.updateMatrixWorld(force)
  26579. if (this.hasPlaybackControl === true && this.isPlaying === false) return
  26580. this.matrixWorld.decompose(_position, _quaternion, _scale)
  26581. _orientation.set(0, 0, 1).applyQuaternion(_quaternion)
  26582. const panner = this.panner
  26583. if (panner.positionX) {
  26584. // code path for Chrome and Firefox (see #14393)
  26585. const endTime = this.context.currentTime + this.listener.timeDelta
  26586. panner.positionX.linearRampToValueAtTime(_position.x, endTime)
  26587. panner.positionY.linearRampToValueAtTime(_position.y, endTime)
  26588. panner.positionZ.linearRampToValueAtTime(_position.z, endTime)
  26589. panner.orientationX.linearRampToValueAtTime(_orientation.x, endTime)
  26590. panner.orientationY.linearRampToValueAtTime(_orientation.y, endTime)
  26591. panner.orientationZ.linearRampToValueAtTime(_orientation.z, endTime)
  26592. } else {
  26593. panner.setPosition(_position.x, _position.y, _position.z)
  26594. panner.setOrientation(_orientation.x, _orientation.y, _orientation.z)
  26595. }
  26596. }
  26597. }
  26598. class AudioAnalyser {
  26599. constructor(audio, fftSize = 2048) {
  26600. this.analyser = audio.context.createAnalyser()
  26601. this.analyser.fftSize = fftSize
  26602. this.data = new Uint8Array(this.analyser.frequencyBinCount)
  26603. audio.getOutput().connect(this.analyser)
  26604. }
  26605. getFrequencyData() {
  26606. this.analyser.getByteFrequencyData(this.data)
  26607. return this.data
  26608. }
  26609. getAverageFrequency() {
  26610. let value = 0
  26611. const data = this.getFrequencyData()
  26612. for (let i = 0; i < data.length; i++) {
  26613. value += data[i]
  26614. }
  26615. return value / data.length
  26616. }
  26617. }
  26618. class PropertyMixer {
  26619. constructor(binding, typeName, valueSize) {
  26620. this.binding = binding
  26621. this.valueSize = valueSize
  26622. let mixFunction, mixFunctionAdditive, setIdentity
  26623. // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
  26624. //
  26625. // interpolators can use .buffer as their .result
  26626. // the data then goes to 'incoming'
  26627. //
  26628. // 'accu0' and 'accu1' are used frame-interleaved for
  26629. // the cumulative result and are compared to detect
  26630. // changes
  26631. //
  26632. // 'orig' stores the original state of the property
  26633. //
  26634. // 'add' is used for additive cumulative results
  26635. //
  26636. // 'work' is optional and is only present for quaternion types. It is used
  26637. // to store intermediate quaternion multiplication results
  26638. switch (typeName) {
  26639. case 'quaternion':
  26640. mixFunction = this._slerp
  26641. mixFunctionAdditive = this._slerpAdditive
  26642. setIdentity = this._setAdditiveIdentityQuaternion
  26643. this.buffer = new Float64Array(valueSize * 6)
  26644. this._workIndex = 5
  26645. break
  26646. case 'string':
  26647. case 'bool':
  26648. mixFunction = this._select
  26649. // Use the regular mix function and for additive on these types,
  26650. // additive is not relevant for non-numeric types
  26651. mixFunctionAdditive = this._select
  26652. setIdentity = this._setAdditiveIdentityOther
  26653. this.buffer = new Array(valueSize * 5)
  26654. break
  26655. default:
  26656. mixFunction = this._lerp
  26657. mixFunctionAdditive = this._lerpAdditive
  26658. setIdentity = this._setAdditiveIdentityNumeric
  26659. this.buffer = new Float64Array(valueSize * 5)
  26660. }
  26661. this._mixBufferRegion = mixFunction
  26662. this._mixBufferRegionAdditive = mixFunctionAdditive
  26663. this._setIdentity = setIdentity
  26664. this._origIndex = 3
  26665. this._addIndex = 4
  26666. this.cumulativeWeight = 0
  26667. this.cumulativeWeightAdditive = 0
  26668. this.useCount = 0
  26669. this.referenceCount = 0
  26670. }
  26671. // accumulate data in the 'incoming' region into 'accu<i>'
  26672. accumulate(accuIndex, weight) {
  26673. // note: happily accumulating nothing when weight = 0, the caller knows
  26674. // the weight and shouldn't have made the call in the first place
  26675. const buffer = this.buffer,
  26676. stride = this.valueSize,
  26677. offset = accuIndex * stride + stride
  26678. let currentWeight = this.cumulativeWeight
  26679. if (currentWeight === 0) {
  26680. // accuN := incoming * weight
  26681. for (let i = 0; i !== stride; ++i) {
  26682. buffer[offset + i] = buffer[i]
  26683. }
  26684. currentWeight = weight
  26685. } else {
  26686. // accuN := accuN + incoming * weight
  26687. currentWeight += weight
  26688. const mix = weight / currentWeight
  26689. this._mixBufferRegion(buffer, offset, 0, mix, stride)
  26690. }
  26691. this.cumulativeWeight = currentWeight
  26692. }
  26693. // accumulate data in the 'incoming' region into 'add'
  26694. accumulateAdditive(weight) {
  26695. const buffer = this.buffer,
  26696. stride = this.valueSize,
  26697. offset = stride * this._addIndex
  26698. if (this.cumulativeWeightAdditive === 0) {
  26699. // add = identity
  26700. this._setIdentity()
  26701. }
  26702. // add := add + incoming * weight
  26703. this._mixBufferRegionAdditive(buffer, offset, 0, weight, stride)
  26704. this.cumulativeWeightAdditive += weight
  26705. }
  26706. // apply the state of 'accu<i>' to the binding when accus differ
  26707. apply(accuIndex) {
  26708. const stride = this.valueSize,
  26709. buffer = this.buffer,
  26710. offset = accuIndex * stride + stride,
  26711. weight = this.cumulativeWeight,
  26712. weightAdditive = this.cumulativeWeightAdditive,
  26713. binding = this.binding
  26714. this.cumulativeWeight = 0
  26715. this.cumulativeWeightAdditive = 0
  26716. if (weight < 1) {
  26717. // accuN := accuN + original * ( 1 - cumulativeWeight )
  26718. const originalValueOffset = stride * this._origIndex
  26719. this._mixBufferRegion(buffer, offset, originalValueOffset, 1 - weight, stride)
  26720. }
  26721. if (weightAdditive > 0) {
  26722. // accuN := accuN + additive accuN
  26723. this._mixBufferRegionAdditive(buffer, offset, this._addIndex * stride, 1, stride)
  26724. }
  26725. for (let i = stride, e = stride + stride; i !== e; ++i) {
  26726. if (buffer[i] !== buffer[i + stride]) {
  26727. // value has changed -> update scene graph
  26728. binding.setValue(buffer, offset)
  26729. break
  26730. }
  26731. }
  26732. }
  26733. // remember the state of the bound property and copy it to both accus
  26734. saveOriginalState() {
  26735. const binding = this.binding
  26736. const buffer = this.buffer,
  26737. stride = this.valueSize,
  26738. originalValueOffset = stride * this._origIndex
  26739. binding.getValue(buffer, originalValueOffset)
  26740. // accu[0..1] := orig -- initially detect changes against the original
  26741. for (let i = stride, e = originalValueOffset; i !== e; ++i) {
  26742. buffer[i] = buffer[originalValueOffset + (i % stride)]
  26743. }
  26744. // Add to identity for additive
  26745. this._setIdentity()
  26746. this.cumulativeWeight = 0
  26747. this.cumulativeWeightAdditive = 0
  26748. }
  26749. // apply the state previously taken via 'saveOriginalState' to the binding
  26750. restoreOriginalState() {
  26751. const originalValueOffset = this.valueSize * 3
  26752. this.binding.setValue(this.buffer, originalValueOffset)
  26753. }
  26754. _setAdditiveIdentityNumeric() {
  26755. const startIndex = this._addIndex * this.valueSize
  26756. const endIndex = startIndex + this.valueSize
  26757. for (let i = startIndex; i < endIndex; i++) {
  26758. this.buffer[i] = 0
  26759. }
  26760. }
  26761. _setAdditiveIdentityQuaternion() {
  26762. this._setAdditiveIdentityNumeric()
  26763. this.buffer[this._addIndex * this.valueSize + 3] = 1
  26764. }
  26765. _setAdditiveIdentityOther() {
  26766. const startIndex = this._origIndex * this.valueSize
  26767. const targetIndex = this._addIndex * this.valueSize
  26768. for (let i = 0; i < this.valueSize; i++) {
  26769. this.buffer[targetIndex + i] = this.buffer[startIndex + i]
  26770. }
  26771. }
  26772. // mix functions
  26773. _select(buffer, dstOffset, srcOffset, t, stride) {
  26774. if (t >= 0.5) {
  26775. for (let i = 0; i !== stride; ++i) {
  26776. buffer[dstOffset + i] = buffer[srcOffset + i]
  26777. }
  26778. }
  26779. }
  26780. _slerp(buffer, dstOffset, srcOffset, t) {
  26781. Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t)
  26782. }
  26783. _slerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
  26784. const workOffset = this._workIndex * stride
  26785. // Store result in intermediate buffer offset
  26786. Quaternion.multiplyQuaternionsFlat(buffer, workOffset, buffer, dstOffset, buffer, srcOffset)
  26787. // Slerp to the intermediate result
  26788. Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t)
  26789. }
  26790. _lerp(buffer, dstOffset, srcOffset, t, stride) {
  26791. const s = 1 - t
  26792. for (let i = 0; i !== stride; ++i) {
  26793. const j = dstOffset + i
  26794. buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t
  26795. }
  26796. }
  26797. _lerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
  26798. for (let i = 0; i !== stride; ++i) {
  26799. const j = dstOffset + i
  26800. buffer[j] = buffer[j] + buffer[srcOffset + i] * t
  26801. }
  26802. }
  26803. }
  26804. // Characters [].:/ are reserved for track binding syntax.
  26805. const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'
  26806. const _reservedRe = new RegExp('[' + _RESERVED_CHARS_RE + ']', 'g')
  26807. // Attempts to allow node names from any language. ES5's `\w` regexp matches
  26808. // only latin characters, and the unicode \p{L} is not yet supported. So
  26809. // instead, we exclude reserved characters and match everything else.
  26810. const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'
  26811. const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace('\\.', '') + ']'
  26812. // Parent directories, delimited by '/' or ':'. Currently unused, but must
  26813. // be matched to parse the rest of the track name.
  26814. const _directoryRe = /((?:WC+[\/:])*)/.source.replace('WC', _wordChar)
  26815. // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
  26816. const _nodeRe = /(WCOD+)?/.source.replace('WCOD', _wordCharOrDot)
  26817. // Object on target node, and accessor. May not contain reserved
  26818. // characters. Accessor may contain any character except closing bracket.
  26819. const _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace('WC', _wordChar)
  26820. // Property and accessor. May not contain reserved characters. Accessor may
  26821. // contain any non-bracket characters.
  26822. const _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace('WC', _wordChar)
  26823. const _trackRe = new RegExp('' + '^' + _directoryRe + _nodeRe + _objectRe + _propertyRe + '$')
  26824. const _supportedObjectNames = ['material', 'materials', 'bones']
  26825. class Composite {
  26826. constructor(targetGroup, path, optionalParsedPath) {
  26827. const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path)
  26828. this._targetGroup = targetGroup
  26829. this._bindings = targetGroup.subscribe_(path, parsedPath)
  26830. }
  26831. getValue(array, offset) {
  26832. this.bind() // bind all binding
  26833. const firstValidIndex = this._targetGroup.nCachedObjects_,
  26834. binding = this._bindings[firstValidIndex]
  26835. // and only call .getValue on the first
  26836. if (binding !== undefined) binding.getValue(array, offset)
  26837. }
  26838. setValue(array, offset) {
  26839. const bindings = this._bindings
  26840. for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
  26841. bindings[i].setValue(array, offset)
  26842. }
  26843. }
  26844. bind() {
  26845. const bindings = this._bindings
  26846. for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
  26847. bindings[i].bind()
  26848. }
  26849. }
  26850. unbind() {
  26851. const bindings = this._bindings
  26852. for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
  26853. bindings[i].unbind()
  26854. }
  26855. }
  26856. }
  26857. // Note: This class uses a State pattern on a per-method basis:
  26858. // 'bind' sets 'this.getValue' / 'setValue' and shadows the
  26859. // prototype version of these methods with one that represents
  26860. // the bound state. When the property is not found, the methods
  26861. // become no-ops.
  26862. class PropertyBinding {
  26863. constructor(rootNode, path, parsedPath) {
  26864. this.path = path
  26865. this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path)
  26866. this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode
  26867. this.rootNode = rootNode
  26868. // initial state of these methods that calls 'bind'
  26869. this.getValue = this._getValue_unbound
  26870. this.setValue = this._setValue_unbound
  26871. }
  26872. static create(root, path, parsedPath) {
  26873. if (!(root && root.isAnimationObjectGroup)) {
  26874. return new PropertyBinding(root, path, parsedPath)
  26875. } else {
  26876. return new PropertyBinding.Composite(root, path, parsedPath)
  26877. }
  26878. }
  26879. /**
  26880. * Replaces spaces with underscores and removes unsupported characters from
  26881. * node names, to ensure compatibility with parseTrackName().
  26882. *
  26883. * @param {string} name Node name to be sanitized.
  26884. * @return {string}
  26885. */
  26886. static sanitizeNodeName(name) {
  26887. return name.replace(/\s/g, '_').replace(_reservedRe, '')
  26888. }
  26889. static parseTrackName(trackName) {
  26890. const matches = _trackRe.exec(trackName)
  26891. if (matches === null) {
  26892. throw new Error('PropertyBinding: Cannot parse trackName: ' + trackName)
  26893. }
  26894. const results = {
  26895. // directoryName: matches[ 1 ], // (tschw) currently unused
  26896. nodeName: matches[2],
  26897. objectName: matches[3],
  26898. objectIndex: matches[4],
  26899. propertyName: matches[5], // required
  26900. propertyIndex: matches[6]
  26901. }
  26902. const lastDot = results.nodeName && results.nodeName.lastIndexOf('.')
  26903. if (lastDot !== undefined && lastDot !== -1) {
  26904. const objectName = results.nodeName.substring(lastDot + 1)
  26905. // Object names must be checked against an allowlist. Otherwise, there
  26906. // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
  26907. // 'bar' could be the objectName, or part of a nodeName (which can
  26908. // include '.' characters).
  26909. if (_supportedObjectNames.indexOf(objectName) !== -1) {
  26910. results.nodeName = results.nodeName.substring(0, lastDot)
  26911. results.objectName = objectName
  26912. }
  26913. }
  26914. if (results.propertyName === null || results.propertyName.length === 0) {
  26915. throw new Error('PropertyBinding: can not parse propertyName from trackName: ' + trackName)
  26916. }
  26917. return results
  26918. }
  26919. static findNode(root, nodeName) {
  26920. if (nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
  26921. return root
  26922. }
  26923. // search into skeleton bones.
  26924. if (root.skeleton) {
  26925. const bone = root.skeleton.getBoneByName(nodeName)
  26926. if (bone !== undefined) {
  26927. return bone
  26928. }
  26929. }
  26930. // search into node subtree.
  26931. if (root.children) {
  26932. const searchNodeSubtree = function(children) {
  26933. for (let i = 0; i < children.length; i++) {
  26934. const childNode = children[i]
  26935. if (childNode.name === nodeName || childNode.uuid === nodeName) {
  26936. return childNode
  26937. }
  26938. const result = searchNodeSubtree(childNode.children)
  26939. if (result) return result
  26940. }
  26941. return null
  26942. }
  26943. const subTreeNode = searchNodeSubtree(root.children)
  26944. if (subTreeNode) {
  26945. return subTreeNode
  26946. }
  26947. }
  26948. return null
  26949. }
  26950. // these are used to "bind" a nonexistent property
  26951. _getValue_unavailable() {}
  26952. _setValue_unavailable() {}
  26953. // Getters
  26954. _getValue_direct(buffer, offset) {
  26955. buffer[offset] = this.targetObject[this.propertyName]
  26956. }
  26957. _getValue_array(buffer, offset) {
  26958. const source = this.resolvedProperty
  26959. for (let i = 0, n = source.length; i !== n; ++i) {
  26960. buffer[offset++] = source[i]
  26961. }
  26962. }
  26963. _getValue_arrayElement(buffer, offset) {
  26964. buffer[offset] = this.resolvedProperty[this.propertyIndex]
  26965. }
  26966. _getValue_toArray(buffer, offset) {
  26967. this.resolvedProperty.toArray(buffer, offset)
  26968. }
  26969. // Direct
  26970. _setValue_direct(buffer, offset) {
  26971. this.targetObject[this.propertyName] = buffer[offset]
  26972. }
  26973. _setValue_direct_setNeedsUpdate(buffer, offset) {
  26974. this.targetObject[this.propertyName] = buffer[offset]
  26975. this.targetObject.needsUpdate = true
  26976. }
  26977. _setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) {
  26978. this.targetObject[this.propertyName] = buffer[offset]
  26979. this.targetObject.matrixWorldNeedsUpdate = true
  26980. }
  26981. // EntireArray
  26982. _setValue_array(buffer, offset) {
  26983. const dest = this.resolvedProperty
  26984. for (let i = 0, n = dest.length; i !== n; ++i) {
  26985. dest[i] = buffer[offset++]
  26986. }
  26987. }
  26988. _setValue_array_setNeedsUpdate(buffer, offset) {
  26989. const dest = this.resolvedProperty
  26990. for (let i = 0, n = dest.length; i !== n; ++i) {
  26991. dest[i] = buffer[offset++]
  26992. }
  26993. this.targetObject.needsUpdate = true
  26994. }
  26995. _setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) {
  26996. const dest = this.resolvedProperty
  26997. for (let i = 0, n = dest.length; i !== n; ++i) {
  26998. dest[i] = buffer[offset++]
  26999. }
  27000. this.targetObject.matrixWorldNeedsUpdate = true
  27001. }
  27002. // ArrayElement
  27003. _setValue_arrayElement(buffer, offset) {
  27004. this.resolvedProperty[this.propertyIndex] = buffer[offset]
  27005. }
  27006. _setValue_arrayElement_setNeedsUpdate(buffer, offset) {
  27007. this.resolvedProperty[this.propertyIndex] = buffer[offset]
  27008. this.targetObject.needsUpdate = true
  27009. }
  27010. _setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) {
  27011. this.resolvedProperty[this.propertyIndex] = buffer[offset]
  27012. this.targetObject.matrixWorldNeedsUpdate = true
  27013. }
  27014. // HasToFromArray
  27015. _setValue_fromArray(buffer, offset) {
  27016. this.resolvedProperty.fromArray(buffer, offset)
  27017. }
  27018. _setValue_fromArray_setNeedsUpdate(buffer, offset) {
  27019. this.resolvedProperty.fromArray(buffer, offset)
  27020. this.targetObject.needsUpdate = true
  27021. }
  27022. _setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) {
  27023. this.resolvedProperty.fromArray(buffer, offset)
  27024. this.targetObject.matrixWorldNeedsUpdate = true
  27025. }
  27026. _getValue_unbound(targetArray, offset) {
  27027. this.bind()
  27028. this.getValue(targetArray, offset)
  27029. }
  27030. _setValue_unbound(sourceArray, offset) {
  27031. this.bind()
  27032. this.setValue(sourceArray, offset)
  27033. }
  27034. // create getter / setter pair for a property in the scene graph
  27035. bind() {
  27036. let targetObject = this.node
  27037. const parsedPath = this.parsedPath
  27038. const objectName = parsedPath.objectName
  27039. const propertyName = parsedPath.propertyName
  27040. let propertyIndex = parsedPath.propertyIndex
  27041. if (!targetObject) {
  27042. targetObject = PropertyBinding.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode
  27043. this.node = targetObject
  27044. }
  27045. // set fail state so we can just 'return' on error
  27046. this.getValue = this._getValue_unavailable
  27047. this.setValue = this._setValue_unavailable
  27048. // ensure there is a value node
  27049. if (!targetObject) {
  27050. console.error('THREE.PropertyBinding: Trying to update node for track: ' + this.path + " but it wasn't found.")
  27051. return
  27052. }
  27053. if (objectName) {
  27054. let objectIndex = parsedPath.objectIndex
  27055. // special cases were we need to reach deeper into the hierarchy to get the face materials....
  27056. switch (objectName) {
  27057. case 'materials':
  27058. if (!targetObject.material) {
  27059. console.error('THREE.PropertyBinding: Can not bind to material as node does not have a material.', this)
  27060. return
  27061. }
  27062. if (!targetObject.material.materials) {
  27063. console.error('THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this)
  27064. return
  27065. }
  27066. targetObject = targetObject.material.materials
  27067. break
  27068. case 'bones':
  27069. if (!targetObject.skeleton) {
  27070. console.error('THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this)
  27071. return
  27072. }
  27073. // potential future optimization: skip this if propertyIndex is already an integer
  27074. // and convert the integer string to a true integer.
  27075. targetObject = targetObject.skeleton.bones
  27076. // support resolving morphTarget names into indices.
  27077. for (let i = 0; i < targetObject.length; i++) {
  27078. if (targetObject[i].name === objectIndex) {
  27079. objectIndex = i
  27080. break
  27081. }
  27082. }
  27083. break
  27084. default:
  27085. if (targetObject[objectName] === undefined) {
  27086. console.error('THREE.PropertyBinding: Can not bind to objectName of node undefined.', this)
  27087. return
  27088. }
  27089. targetObject = targetObject[objectName]
  27090. }
  27091. if (objectIndex !== undefined) {
  27092. if (targetObject[objectIndex] === undefined) {
  27093. console.error('THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject)
  27094. return
  27095. }
  27096. targetObject = targetObject[objectIndex]
  27097. }
  27098. }
  27099. // resolve property
  27100. const nodeProperty = targetObject[propertyName]
  27101. if (nodeProperty === undefined) {
  27102. const nodeName = parsedPath.nodeName
  27103. console.error('THREE.PropertyBinding: Trying to update property for track: ' + nodeName + '.' + propertyName + " but it wasn't found.", targetObject)
  27104. return
  27105. }
  27106. // determine versioning scheme
  27107. let versioning = this.Versioning.None
  27108. this.targetObject = targetObject
  27109. if (targetObject.needsUpdate !== undefined) {
  27110. // material
  27111. versioning = this.Versioning.NeedsUpdate
  27112. } else if (targetObject.matrixWorldNeedsUpdate !== undefined) {
  27113. // node transform
  27114. versioning = this.Versioning.MatrixWorldNeedsUpdate
  27115. }
  27116. // determine how the property gets bound
  27117. let bindingType = this.BindingType.Direct
  27118. if (propertyIndex !== undefined) {
  27119. // access a sub element of the property array (only primitives are supported right now)
  27120. if (propertyName === 'morphTargetInfluences') {
  27121. // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
  27122. // support resolving morphTarget names into indices.
  27123. if (!targetObject.geometry) {
  27124. console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this)
  27125. return
  27126. }
  27127. if (!targetObject.geometry.morphAttributes) {
  27128. console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this)
  27129. return
  27130. }
  27131. if (targetObject.morphTargetDictionary[propertyIndex] !== undefined) {
  27132. propertyIndex = targetObject.morphTargetDictionary[propertyIndex]
  27133. }
  27134. }
  27135. bindingType = this.BindingType.ArrayElement
  27136. this.resolvedProperty = nodeProperty
  27137. this.propertyIndex = propertyIndex
  27138. } else if (nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined) {
  27139. // must use copy for Object3D.Euler/Quaternion
  27140. bindingType = this.BindingType.HasFromToArray
  27141. this.resolvedProperty = nodeProperty
  27142. } else if (Array.isArray(nodeProperty)) {
  27143. bindingType = this.BindingType.EntireArray
  27144. this.resolvedProperty = nodeProperty
  27145. } else {
  27146. this.propertyName = propertyName
  27147. }
  27148. // select getter / setter
  27149. this.getValue = this.GetterByBindingType[bindingType]
  27150. this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning]
  27151. }
  27152. unbind() {
  27153. this.node = null
  27154. // back to the prototype version of getValue / setValue
  27155. // note: avoiding to mutate the shape of 'this' via 'delete'
  27156. this.getValue = this._getValue_unbound
  27157. this.setValue = this._setValue_unbound
  27158. }
  27159. }
  27160. PropertyBinding.Composite = Composite
  27161. PropertyBinding.prototype.BindingType = {
  27162. Direct: 0,
  27163. EntireArray: 1,
  27164. ArrayElement: 2,
  27165. HasFromToArray: 3
  27166. }
  27167. PropertyBinding.prototype.Versioning = {
  27168. None: 0,
  27169. NeedsUpdate: 1,
  27170. MatrixWorldNeedsUpdate: 2
  27171. }
  27172. PropertyBinding.prototype.GetterByBindingType = [
  27173. PropertyBinding.prototype._getValue_direct,
  27174. PropertyBinding.prototype._getValue_array,
  27175. PropertyBinding.prototype._getValue_arrayElement,
  27176. PropertyBinding.prototype._getValue_toArray
  27177. ]
  27178. PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
  27179. [
  27180. // Direct
  27181. PropertyBinding.prototype._setValue_direct,
  27182. PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
  27183. PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate
  27184. ],
  27185. [
  27186. // EntireArray
  27187. PropertyBinding.prototype._setValue_array,
  27188. PropertyBinding.prototype._setValue_array_setNeedsUpdate,
  27189. PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate
  27190. ],
  27191. [
  27192. // ArrayElement
  27193. PropertyBinding.prototype._setValue_arrayElement,
  27194. PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
  27195. PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate
  27196. ],
  27197. [
  27198. // HasToFromArray
  27199. PropertyBinding.prototype._setValue_fromArray,
  27200. PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
  27201. PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate
  27202. ]
  27203. ]
  27204. /**
  27205. *
  27206. * A group of objects that receives a shared animation state.
  27207. *
  27208. * Usage:
  27209. *
  27210. * - Add objects you would otherwise pass as 'root' to the
  27211. * constructor or the .clipAction method of AnimationMixer.
  27212. *
  27213. * - Instead pass this object as 'root'.
  27214. *
  27215. * - You can also add and remove objects later when the mixer
  27216. * is running.
  27217. *
  27218. * Note:
  27219. *
  27220. * Objects of this class appear as one object to the mixer,
  27221. * so cache control of the individual objects must be done
  27222. * on the group.
  27223. *
  27224. * Limitation:
  27225. *
  27226. * - The animated properties must be compatible among the
  27227. * all objects in the group.
  27228. *
  27229. * - A single property can either be controlled through a
  27230. * target group or directly, but not both.
  27231. */
  27232. class AnimationObjectGroup {
  27233. constructor() {
  27234. this.isAnimationObjectGroup = true
  27235. this.uuid = generateUUID()
  27236. // cached objects followed by the active ones
  27237. this._objects = Array.prototype.slice.call(arguments)
  27238. this.nCachedObjects_ = 0 // threshold
  27239. // note: read by PropertyBinding.Composite
  27240. const indices = {}
  27241. this._indicesByUUID = indices // for bookkeeping
  27242. for (let i = 0, n = arguments.length; i !== n; ++i) {
  27243. indices[arguments[i].uuid] = i
  27244. }
  27245. this._paths = [] // inside: string
  27246. this._parsedPaths = [] // inside: { we don't care, here }
  27247. this._bindings = [] // inside: Array< PropertyBinding >
  27248. this._bindingsIndicesByPath = {} // inside: indices in these arrays
  27249. const scope = this
  27250. this.stats = {
  27251. objects: {
  27252. get total() {
  27253. return scope._objects.length
  27254. },
  27255. get inUse() {
  27256. return this.total - scope.nCachedObjects_
  27257. }
  27258. },
  27259. get bindingsPerObject() {
  27260. return scope._bindings.length
  27261. }
  27262. }
  27263. }
  27264. add() {
  27265. const objects = this._objects,
  27266. indicesByUUID = this._indicesByUUID,
  27267. paths = this._paths,
  27268. parsedPaths = this._parsedPaths,
  27269. bindings = this._bindings,
  27270. nBindings = bindings.length
  27271. let knownObject = undefined,
  27272. nObjects = objects.length,
  27273. nCachedObjects = this.nCachedObjects_
  27274. for (let i = 0, n = arguments.length; i !== n; ++i) {
  27275. const object = arguments[i],
  27276. uuid = object.uuid
  27277. let index = indicesByUUID[uuid]
  27278. if (index === undefined) {
  27279. // unknown object -> add it to the ACTIVE region
  27280. index = nObjects++
  27281. indicesByUUID[uuid] = index
  27282. objects.push(object)
  27283. // accounting is done, now do the same for all bindings
  27284. for (let j = 0, m = nBindings; j !== m; ++j) {
  27285. bindings[j].push(new PropertyBinding(object, paths[j], parsedPaths[j]))
  27286. }
  27287. } else if (index < nCachedObjects) {
  27288. knownObject = objects[index]
  27289. // move existing object to the ACTIVE region
  27290. const firstActiveIndex = --nCachedObjects,
  27291. lastCachedObject = objects[firstActiveIndex]
  27292. indicesByUUID[lastCachedObject.uuid] = index
  27293. objects[index] = lastCachedObject
  27294. indicesByUUID[uuid] = firstActiveIndex
  27295. objects[firstActiveIndex] = object
  27296. // accounting is done, now do the same for all bindings
  27297. for (let j = 0, m = nBindings; j !== m; ++j) {
  27298. const bindingsForPath = bindings[j],
  27299. lastCached = bindingsForPath[firstActiveIndex]
  27300. let binding = bindingsForPath[index]
  27301. bindingsForPath[index] = lastCached
  27302. if (binding === undefined) {
  27303. // since we do not bother to create new bindings
  27304. // for objects that are cached, the binding may
  27305. // or may not exist
  27306. binding = new PropertyBinding(object, paths[j], parsedPaths[j])
  27307. }
  27308. bindingsForPath[firstActiveIndex] = binding
  27309. }
  27310. } else if (objects[index] !== knownObject) {
  27311. console.error('THREE.AnimationObjectGroup: Different objects with the same UUID ' + 'detected. Clean the caches or recreate your infrastructure when reloading scenes.')
  27312. } // else the object is already where we want it to be
  27313. } // for arguments
  27314. this.nCachedObjects_ = nCachedObjects
  27315. }
  27316. remove() {
  27317. const objects = this._objects,
  27318. indicesByUUID = this._indicesByUUID,
  27319. bindings = this._bindings,
  27320. nBindings = bindings.length
  27321. let nCachedObjects = this.nCachedObjects_
  27322. for (let i = 0, n = arguments.length; i !== n; ++i) {
  27323. const object = arguments[i],
  27324. uuid = object.uuid,
  27325. index = indicesByUUID[uuid]
  27326. if (index !== undefined && index >= nCachedObjects) {
  27327. // move existing object into the CACHED region
  27328. const lastCachedIndex = nCachedObjects++,
  27329. firstActiveObject = objects[lastCachedIndex]
  27330. indicesByUUID[firstActiveObject.uuid] = index
  27331. objects[index] = firstActiveObject
  27332. indicesByUUID[uuid] = lastCachedIndex
  27333. objects[lastCachedIndex] = object
  27334. // accounting is done, now do the same for all bindings
  27335. for (let j = 0, m = nBindings; j !== m; ++j) {
  27336. const bindingsForPath = bindings[j],
  27337. firstActive = bindingsForPath[lastCachedIndex],
  27338. binding = bindingsForPath[index]
  27339. bindingsForPath[index] = firstActive
  27340. bindingsForPath[lastCachedIndex] = binding
  27341. }
  27342. }
  27343. } // for arguments
  27344. this.nCachedObjects_ = nCachedObjects
  27345. }
  27346. // remove & forget
  27347. uncache() {
  27348. const objects = this._objects,
  27349. indicesByUUID = this._indicesByUUID,
  27350. bindings = this._bindings,
  27351. nBindings = bindings.length
  27352. let nCachedObjects = this.nCachedObjects_,
  27353. nObjects = objects.length
  27354. for (let i = 0, n = arguments.length; i !== n; ++i) {
  27355. const object = arguments[i],
  27356. uuid = object.uuid,
  27357. index = indicesByUUID[uuid]
  27358. if (index !== undefined) {
  27359. delete indicesByUUID[uuid]
  27360. if (index < nCachedObjects) {
  27361. // object is cached, shrink the CACHED region
  27362. const firstActiveIndex = --nCachedObjects,
  27363. lastCachedObject = objects[firstActiveIndex],
  27364. lastIndex = --nObjects,
  27365. lastObject = objects[lastIndex]
  27366. // last cached object takes this object's place
  27367. indicesByUUID[lastCachedObject.uuid] = index
  27368. objects[index] = lastCachedObject
  27369. // last object goes to the activated slot and pop
  27370. indicesByUUID[lastObject.uuid] = firstActiveIndex
  27371. objects[firstActiveIndex] = lastObject
  27372. objects.pop()
  27373. // accounting is done, now do the same for all bindings
  27374. for (let j = 0, m = nBindings; j !== m; ++j) {
  27375. const bindingsForPath = bindings[j],
  27376. lastCached = bindingsForPath[firstActiveIndex],
  27377. last = bindingsForPath[lastIndex]
  27378. bindingsForPath[index] = lastCached
  27379. bindingsForPath[firstActiveIndex] = last
  27380. bindingsForPath.pop()
  27381. }
  27382. } else {
  27383. // object is active, just swap with the last and pop
  27384. const lastIndex = --nObjects,
  27385. lastObject = objects[lastIndex]
  27386. if (lastIndex > 0) {
  27387. indicesByUUID[lastObject.uuid] = index
  27388. }
  27389. objects[index] = lastObject
  27390. objects.pop()
  27391. // accounting is done, now do the same for all bindings
  27392. for (let j = 0, m = nBindings; j !== m; ++j) {
  27393. const bindingsForPath = bindings[j]
  27394. bindingsForPath[index] = bindingsForPath[lastIndex]
  27395. bindingsForPath.pop()
  27396. }
  27397. } // cached or active
  27398. } // if object is known
  27399. } // for arguments
  27400. this.nCachedObjects_ = nCachedObjects
  27401. }
  27402. // Internal interface used by befriended PropertyBinding.Composite:
  27403. subscribe_(path, parsedPath) {
  27404. // returns an array of bindings for the given path that is changed
  27405. // according to the contained objects in the group
  27406. const indicesByPath = this._bindingsIndicesByPath
  27407. let index = indicesByPath[path]
  27408. const bindings = this._bindings
  27409. if (index !== undefined) return bindings[index]
  27410. const paths = this._paths,
  27411. parsedPaths = this._parsedPaths,
  27412. objects = this._objects,
  27413. nObjects = objects.length,
  27414. nCachedObjects = this.nCachedObjects_,
  27415. bindingsForPath = new Array(nObjects)
  27416. index = bindings.length
  27417. indicesByPath[path] = index
  27418. paths.push(path)
  27419. parsedPaths.push(parsedPath)
  27420. bindings.push(bindingsForPath)
  27421. for (let i = nCachedObjects, n = objects.length; i !== n; ++i) {
  27422. const object = objects[i]
  27423. bindingsForPath[i] = new PropertyBinding(object, path, parsedPath)
  27424. }
  27425. return bindingsForPath
  27426. }
  27427. unsubscribe_(path) {
  27428. // tells the group to forget about a property path and no longer
  27429. // update the array previously obtained with 'subscribe_'
  27430. const indicesByPath = this._bindingsIndicesByPath,
  27431. index = indicesByPath[path]
  27432. if (index !== undefined) {
  27433. const paths = this._paths,
  27434. parsedPaths = this._parsedPaths,
  27435. bindings = this._bindings,
  27436. lastBindingsIndex = bindings.length - 1,
  27437. lastBindings = bindings[lastBindingsIndex],
  27438. lastBindingsPath = path[lastBindingsIndex]
  27439. indicesByPath[lastBindingsPath] = index
  27440. bindings[index] = lastBindings
  27441. bindings.pop()
  27442. parsedPaths[index] = parsedPaths[lastBindingsIndex]
  27443. parsedPaths.pop()
  27444. paths[index] = paths[lastBindingsIndex]
  27445. paths.pop()
  27446. }
  27447. }
  27448. }
  27449. class AnimationAction {
  27450. constructor(mixer, clip, localRoot = null, blendMode = clip.blendMode) {
  27451. this._mixer = mixer
  27452. this._clip = clip
  27453. this._localRoot = localRoot
  27454. this.blendMode = blendMode
  27455. const tracks = clip.tracks,
  27456. nTracks = tracks.length,
  27457. interpolants = new Array(nTracks)
  27458. const interpolantSettings = {
  27459. endingStart: ZeroCurvatureEnding,
  27460. endingEnd: ZeroCurvatureEnding
  27461. }
  27462. for (let i = 0; i !== nTracks; ++i) {
  27463. const interpolant = tracks[i].createInterpolant(null)
  27464. interpolants[i] = interpolant
  27465. interpolant.settings = interpolantSettings
  27466. }
  27467. this._interpolantSettings = interpolantSettings
  27468. this._interpolants = interpolants // bound by the mixer
  27469. // inside: PropertyMixer (managed by the mixer)
  27470. this._propertyBindings = new Array(nTracks)
  27471. this._cacheIndex = null // for the memory manager
  27472. this._byClipCacheIndex = null // for the memory manager
  27473. this._timeScaleInterpolant = null
  27474. this._weightInterpolant = null
  27475. this.loop = LoopRepeat
  27476. this._loopCount = -1
  27477. // global mixer time when the action is to be started
  27478. // it's set back to 'null' upon start of the action
  27479. this._startTime = null
  27480. // scaled local time of the action
  27481. // gets clamped or wrapped to 0..clip.duration according to loop
  27482. this.time = 0
  27483. this.timeScale = 1
  27484. this._effectiveTimeScale = 1
  27485. this.weight = 1
  27486. this._effectiveWeight = 1
  27487. this.repetitions = Infinity // no. of repetitions when looping
  27488. this.paused = false // true -> zero effective time scale
  27489. this.enabled = true // false -> zero effective weight
  27490. this.clampWhenFinished = false // keep feeding the last frame?
  27491. this.zeroSlopeAtStart = true // for smooth interpolation w/o separate
  27492. this.zeroSlopeAtEnd = true // clips for start, loop and end
  27493. }
  27494. // State & Scheduling
  27495. play() {
  27496. this._mixer._activateAction(this)
  27497. return this
  27498. }
  27499. stop() {
  27500. this._mixer._deactivateAction(this)
  27501. return this.reset()
  27502. }
  27503. reset() {
  27504. this.paused = false
  27505. this.enabled = true
  27506. this.time = 0 // restart clip
  27507. this._loopCount = -1 // forget previous loops
  27508. this._startTime = null // forget scheduling
  27509. return this.stopFading().stopWarping()
  27510. }
  27511. isRunning() {
  27512. return this.enabled && !this.paused && this.timeScale !== 0 && this._startTime === null && this._mixer._isActiveAction(this)
  27513. }
  27514. // return true when play has been called
  27515. isScheduled() {
  27516. return this._mixer._isActiveAction(this)
  27517. }
  27518. startAt(time) {
  27519. this._startTime = time
  27520. return this
  27521. }
  27522. setLoop(mode, repetitions) {
  27523. this.loop = mode
  27524. this.repetitions = repetitions
  27525. return this
  27526. }
  27527. // Weight
  27528. // set the weight stopping any scheduled fading
  27529. // although .enabled = false yields an effective weight of zero, this
  27530. // method does *not* change .enabled, because it would be confusing
  27531. setEffectiveWeight(weight) {
  27532. this.weight = weight
  27533. // note: same logic as when updated at runtime
  27534. this._effectiveWeight = this.enabled ? weight : 0
  27535. return this.stopFading()
  27536. }
  27537. // return the weight considering fading and .enabled
  27538. getEffectiveWeight() {
  27539. return this._effectiveWeight
  27540. }
  27541. fadeIn(duration) {
  27542. return this._scheduleFading(duration, 0, 1)
  27543. }
  27544. fadeOut(duration) {
  27545. return this._scheduleFading(duration, 1, 0)
  27546. }
  27547. crossFadeFrom(fadeOutAction, duration, warp) {
  27548. fadeOutAction.fadeOut(duration)
  27549. this.fadeIn(duration)
  27550. if (warp) {
  27551. const fadeInDuration = this._clip.duration,
  27552. fadeOutDuration = fadeOutAction._clip.duration,
  27553. startEndRatio = fadeOutDuration / fadeInDuration,
  27554. endStartRatio = fadeInDuration / fadeOutDuration
  27555. fadeOutAction.warp(1.0, startEndRatio, duration)
  27556. this.warp(endStartRatio, 1.0, duration)
  27557. }
  27558. return this
  27559. }
  27560. crossFadeTo(fadeInAction, duration, warp) {
  27561. return fadeInAction.crossFadeFrom(this, duration, warp)
  27562. }
  27563. stopFading() {
  27564. const weightInterpolant = this._weightInterpolant
  27565. if (weightInterpolant !== null) {
  27566. this._weightInterpolant = null
  27567. this._mixer._takeBackControlInterpolant(weightInterpolant)
  27568. }
  27569. return this
  27570. }
  27571. // Time Scale Control
  27572. // set the time scale stopping any scheduled warping
  27573. // although .paused = true yields an effective time scale of zero, this
  27574. // method does *not* change .paused, because it would be confusing
  27575. setEffectiveTimeScale(timeScale) {
  27576. this.timeScale = timeScale
  27577. this._effectiveTimeScale = this.paused ? 0 : timeScale
  27578. return this.stopWarping()
  27579. }
  27580. // return the time scale considering warping and .paused
  27581. getEffectiveTimeScale() {
  27582. return this._effectiveTimeScale
  27583. }
  27584. setDuration(duration) {
  27585. this.timeScale = this._clip.duration / duration
  27586. return this.stopWarping()
  27587. }
  27588. syncWith(action) {
  27589. this.time = action.time
  27590. this.timeScale = action.timeScale
  27591. return this.stopWarping()
  27592. }
  27593. halt(duration) {
  27594. return this.warp(this._effectiveTimeScale, 0, duration)
  27595. }
  27596. warp(startTimeScale, endTimeScale, duration) {
  27597. const mixer = this._mixer,
  27598. now = mixer.time,
  27599. timeScale = this.timeScale
  27600. let interpolant = this._timeScaleInterpolant
  27601. if (interpolant === null) {
  27602. interpolant = mixer._lendControlInterpolant()
  27603. this._timeScaleInterpolant = interpolant
  27604. }
  27605. const times = interpolant.parameterPositions,
  27606. values = interpolant.sampleValues
  27607. times[0] = now
  27608. times[1] = now + duration
  27609. values[0] = startTimeScale / timeScale
  27610. values[1] = endTimeScale / timeScale
  27611. return this
  27612. }
  27613. stopWarping() {
  27614. const timeScaleInterpolant = this._timeScaleInterpolant
  27615. if (timeScaleInterpolant !== null) {
  27616. this._timeScaleInterpolant = null
  27617. this._mixer._takeBackControlInterpolant(timeScaleInterpolant)
  27618. }
  27619. return this
  27620. }
  27621. // Object Accessors
  27622. getMixer() {
  27623. return this._mixer
  27624. }
  27625. getClip() {
  27626. return this._clip
  27627. }
  27628. getRoot() {
  27629. return this._localRoot || this._mixer._root
  27630. }
  27631. // Interna
  27632. _update(time, deltaTime, timeDirection, accuIndex) {
  27633. // called by the mixer
  27634. if (!this.enabled) {
  27635. // call ._updateWeight() to update ._effectiveWeight
  27636. this._updateWeight(time)
  27637. return
  27638. }
  27639. const startTime = this._startTime
  27640. if (startTime !== null) {
  27641. // check for scheduled start of action
  27642. const timeRunning = (time - startTime) * timeDirection
  27643. if (timeRunning < 0 || timeDirection === 0) {
  27644. return // yet to come / don't decide when delta = 0
  27645. }
  27646. // start
  27647. this._startTime = null // unschedule
  27648. deltaTime = timeDirection * timeRunning
  27649. }
  27650. // apply time scale and advance time
  27651. deltaTime *= this._updateTimeScale(time)
  27652. const clipTime = this._updateTime(deltaTime)
  27653. // note: _updateTime may disable the action resulting in
  27654. // an effective weight of 0
  27655. const weight = this._updateWeight(time)
  27656. if (weight > 0) {
  27657. const interpolants = this._interpolants
  27658. const propertyMixers = this._propertyBindings
  27659. switch (this.blendMode) {
  27660. case AdditiveAnimationBlendMode:
  27661. for (let j = 0, m = interpolants.length; j !== m; ++j) {
  27662. interpolants[j].evaluate(clipTime)
  27663. propertyMixers[j].accumulateAdditive(weight)
  27664. }
  27665. break
  27666. case NormalAnimationBlendMode:
  27667. default:
  27668. for (let j = 0, m = interpolants.length; j !== m; ++j) {
  27669. interpolants[j].evaluate(clipTime)
  27670. propertyMixers[j].accumulate(accuIndex, weight)
  27671. }
  27672. }
  27673. }
  27674. }
  27675. _updateWeight(time) {
  27676. let weight = 0
  27677. if (this.enabled) {
  27678. weight = this.weight
  27679. const interpolant = this._weightInterpolant
  27680. if (interpolant !== null) {
  27681. const interpolantValue = interpolant.evaluate(time)[0]
  27682. weight *= interpolantValue
  27683. if (time > interpolant.parameterPositions[1]) {
  27684. this.stopFading()
  27685. if (interpolantValue === 0) {
  27686. // faded out, disable
  27687. this.enabled = false
  27688. }
  27689. }
  27690. }
  27691. }
  27692. this._effectiveWeight = weight
  27693. return weight
  27694. }
  27695. _updateTimeScale(time) {
  27696. let timeScale = 0
  27697. if (!this.paused) {
  27698. timeScale = this.timeScale
  27699. const interpolant = this._timeScaleInterpolant
  27700. if (interpolant !== null) {
  27701. const interpolantValue = interpolant.evaluate(time)[0]
  27702. timeScale *= interpolantValue
  27703. if (time > interpolant.parameterPositions[1]) {
  27704. this.stopWarping()
  27705. if (timeScale === 0) {
  27706. // motion has halted, pause
  27707. this.paused = true
  27708. } else {
  27709. // warp done - apply final time scale
  27710. this.timeScale = timeScale
  27711. }
  27712. }
  27713. }
  27714. }
  27715. this._effectiveTimeScale = timeScale
  27716. return timeScale
  27717. }
  27718. _updateTime(deltaTime) {
  27719. const duration = this._clip.duration
  27720. const loop = this.loop
  27721. let time = this.time + deltaTime
  27722. let loopCount = this._loopCount
  27723. const pingPong = loop === LoopPingPong
  27724. if (deltaTime === 0) {
  27725. if (loopCount === -1) return time
  27726. return pingPong && (loopCount & 1) === 1 ? duration - time : time
  27727. }
  27728. if (loop === LoopOnce) {
  27729. if (loopCount === -1) {
  27730. // just started
  27731. this._loopCount = 0
  27732. this._setEndings(true, true, false)
  27733. }
  27734. handle_stop: {
  27735. if (time >= duration) {
  27736. time = duration
  27737. } else if (time < 0) {
  27738. time = 0
  27739. } else {
  27740. this.time = time
  27741. break handle_stop
  27742. }
  27743. if (this.clampWhenFinished) this.paused = true
  27744. else this.enabled = false
  27745. this.time = time
  27746. this._mixer.dispatchEvent({
  27747. type: 'finished',
  27748. action: this,
  27749. direction: deltaTime < 0 ? -1 : 1
  27750. })
  27751. }
  27752. } else {
  27753. // repetitive Repeat or PingPong
  27754. if (loopCount === -1) {
  27755. // just started
  27756. if (deltaTime >= 0) {
  27757. loopCount = 0
  27758. this._setEndings(true, this.repetitions === 0, pingPong)
  27759. } else {
  27760. // when looping in reverse direction, the initial
  27761. // transition through zero counts as a repetition,
  27762. // so leave loopCount at -1
  27763. this._setEndings(this.repetitions === 0, true, pingPong)
  27764. }
  27765. }
  27766. if (time >= duration || time < 0) {
  27767. // wrap around
  27768. const loopDelta = Math.floor(time / duration) // signed
  27769. time -= duration * loopDelta
  27770. loopCount += Math.abs(loopDelta)
  27771. const pending = this.repetitions - loopCount
  27772. if (pending <= 0) {
  27773. // have to stop (switch state, clamp time, fire event)
  27774. if (this.clampWhenFinished) this.paused = true
  27775. else this.enabled = false
  27776. time = deltaTime > 0 ? duration : 0
  27777. this.time = time
  27778. this._mixer.dispatchEvent({
  27779. type: 'finished',
  27780. action: this,
  27781. direction: deltaTime > 0 ? 1 : -1
  27782. })
  27783. } else {
  27784. // keep running
  27785. if (pending === 1) {
  27786. // entering the last round
  27787. const atStart = deltaTime < 0
  27788. this._setEndings(atStart, !atStart, pingPong)
  27789. } else {
  27790. this._setEndings(false, false, pingPong)
  27791. }
  27792. this._loopCount = loopCount
  27793. this.time = time
  27794. this._mixer.dispatchEvent({
  27795. type: 'loop',
  27796. action: this,
  27797. loopDelta: loopDelta
  27798. })
  27799. }
  27800. } else {
  27801. this.time = time
  27802. }
  27803. if (pingPong && (loopCount & 1) === 1) {
  27804. // invert time for the "pong round"
  27805. return duration - time
  27806. }
  27807. }
  27808. return time
  27809. }
  27810. _setEndings(atStart, atEnd, pingPong) {
  27811. const settings = this._interpolantSettings
  27812. if (pingPong) {
  27813. settings.endingStart = ZeroSlopeEnding
  27814. settings.endingEnd = ZeroSlopeEnding
  27815. } else {
  27816. // assuming for LoopOnce atStart == atEnd == true
  27817. if (atStart) {
  27818. settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding
  27819. } else {
  27820. settings.endingStart = WrapAroundEnding
  27821. }
  27822. if (atEnd) {
  27823. settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding
  27824. } else {
  27825. settings.endingEnd = WrapAroundEnding
  27826. }
  27827. }
  27828. }
  27829. _scheduleFading(duration, weightNow, weightThen) {
  27830. const mixer = this._mixer,
  27831. now = mixer.time
  27832. let interpolant = this._weightInterpolant
  27833. if (interpolant === null) {
  27834. interpolant = mixer._lendControlInterpolant()
  27835. this._weightInterpolant = interpolant
  27836. }
  27837. const times = interpolant.parameterPositions,
  27838. values = interpolant.sampleValues
  27839. times[0] = now
  27840. values[0] = weightNow
  27841. times[1] = now + duration
  27842. values[1] = weightThen
  27843. return this
  27844. }
  27845. }
  27846. const _controlInterpolantsResultBuffer = /*@__PURE__*/ new Float32Array(1)
  27847. class AnimationMixer extends EventDispatcher {
  27848. constructor(root) {
  27849. super()
  27850. this._root = root
  27851. this._initMemoryManager()
  27852. this._accuIndex = 0
  27853. this.time = 0
  27854. this.timeScale = 1.0
  27855. }
  27856. _bindAction(action, prototypeAction) {
  27857. const root = action._localRoot || this._root,
  27858. tracks = action._clip.tracks,
  27859. nTracks = tracks.length,
  27860. bindings = action._propertyBindings,
  27861. interpolants = action._interpolants,
  27862. rootUuid = root.uuid,
  27863. bindingsByRoot = this._bindingsByRootAndName
  27864. let bindingsByName = bindingsByRoot[rootUuid]
  27865. if (bindingsByName === undefined) {
  27866. bindingsByName = {}
  27867. bindingsByRoot[rootUuid] = bindingsByName
  27868. }
  27869. for (let i = 0; i !== nTracks; ++i) {
  27870. const track = tracks[i],
  27871. trackName = track.name
  27872. let binding = bindingsByName[trackName]
  27873. if (binding !== undefined) {
  27874. ++binding.referenceCount
  27875. bindings[i] = binding
  27876. } else {
  27877. binding = bindings[i]
  27878. if (binding !== undefined) {
  27879. // existing binding, make sure the cache knows
  27880. if (binding._cacheIndex === null) {
  27881. ++binding.referenceCount
  27882. this._addInactiveBinding(binding, rootUuid, trackName)
  27883. }
  27884. continue
  27885. }
  27886. const path = prototypeAction && prototypeAction._propertyBindings[i].binding.parsedPath
  27887. binding = new PropertyMixer(PropertyBinding.create(root, trackName, path), track.ValueTypeName, track.getValueSize())
  27888. ++binding.referenceCount
  27889. this._addInactiveBinding(binding, rootUuid, trackName)
  27890. bindings[i] = binding
  27891. }
  27892. interpolants[i].resultBuffer = binding.buffer
  27893. }
  27894. }
  27895. _activateAction(action) {
  27896. if (!this._isActiveAction(action)) {
  27897. if (action._cacheIndex === null) {
  27898. // this action has been forgotten by the cache, but the user
  27899. // appears to be still using it -> rebind
  27900. const rootUuid = (action._localRoot || this._root).uuid,
  27901. clipUuid = action._clip.uuid,
  27902. actionsForClip = this._actionsByClip[clipUuid]
  27903. this._bindAction(action, actionsForClip && actionsForClip.knownActions[0])
  27904. this._addInactiveAction(action, clipUuid, rootUuid)
  27905. }
  27906. const bindings = action._propertyBindings
  27907. // increment reference counts / sort out state
  27908. for (let i = 0, n = bindings.length; i !== n; ++i) {
  27909. const binding = bindings[i]
  27910. if (binding.useCount++ === 0) {
  27911. this._lendBinding(binding)
  27912. binding.saveOriginalState()
  27913. }
  27914. }
  27915. this._lendAction(action)
  27916. }
  27917. }
  27918. _deactivateAction(action) {
  27919. if (this._isActiveAction(action)) {
  27920. const bindings = action._propertyBindings
  27921. // decrement reference counts / sort out state
  27922. for (let i = 0, n = bindings.length; i !== n; ++i) {
  27923. const binding = bindings[i]
  27924. if (--binding.useCount === 0) {
  27925. binding.restoreOriginalState()
  27926. this._takeBackBinding(binding)
  27927. }
  27928. }
  27929. this._takeBackAction(action)
  27930. }
  27931. }
  27932. // Memory manager
  27933. _initMemoryManager() {
  27934. this._actions = [] // 'nActiveActions' followed by inactive ones
  27935. this._nActiveActions = 0
  27936. this._actionsByClip = {}
  27937. // inside:
  27938. // {
  27939. // knownActions: Array< AnimationAction > - used as prototypes
  27940. // actionByRoot: AnimationAction - lookup
  27941. // }
  27942. this._bindings = [] // 'nActiveBindings' followed by inactive ones
  27943. this._nActiveBindings = 0
  27944. this._bindingsByRootAndName = {} // inside: Map< name, PropertyMixer >
  27945. this._controlInterpolants = [] // same game as above
  27946. this._nActiveControlInterpolants = 0
  27947. const scope = this
  27948. this.stats = {
  27949. actions: {
  27950. get total() {
  27951. return scope._actions.length
  27952. },
  27953. get inUse() {
  27954. return scope._nActiveActions
  27955. }
  27956. },
  27957. bindings: {
  27958. get total() {
  27959. return scope._bindings.length
  27960. },
  27961. get inUse() {
  27962. return scope._nActiveBindings
  27963. }
  27964. },
  27965. controlInterpolants: {
  27966. get total() {
  27967. return scope._controlInterpolants.length
  27968. },
  27969. get inUse() {
  27970. return scope._nActiveControlInterpolants
  27971. }
  27972. }
  27973. }
  27974. }
  27975. // Memory management for AnimationAction objects
  27976. _isActiveAction(action) {
  27977. const index = action._cacheIndex
  27978. return index !== null && index < this._nActiveActions
  27979. }
  27980. _addInactiveAction(action, clipUuid, rootUuid) {
  27981. const actions = this._actions,
  27982. actionsByClip = this._actionsByClip
  27983. let actionsForClip = actionsByClip[clipUuid]
  27984. if (actionsForClip === undefined) {
  27985. actionsForClip = {
  27986. knownActions: [action],
  27987. actionByRoot: {}
  27988. }
  27989. action._byClipCacheIndex = 0
  27990. actionsByClip[clipUuid] = actionsForClip
  27991. } else {
  27992. const knownActions = actionsForClip.knownActions
  27993. action._byClipCacheIndex = knownActions.length
  27994. knownActions.push(action)
  27995. }
  27996. action._cacheIndex = actions.length
  27997. actions.push(action)
  27998. actionsForClip.actionByRoot[rootUuid] = action
  27999. }
  28000. _removeInactiveAction(action) {
  28001. const actions = this._actions,
  28002. lastInactiveAction = actions[actions.length - 1],
  28003. cacheIndex = action._cacheIndex
  28004. lastInactiveAction._cacheIndex = cacheIndex
  28005. actions[cacheIndex] = lastInactiveAction
  28006. actions.pop()
  28007. action._cacheIndex = null
  28008. const clipUuid = action._clip.uuid,
  28009. actionsByClip = this._actionsByClip,
  28010. actionsForClip = actionsByClip[clipUuid],
  28011. knownActionsForClip = actionsForClip.knownActions,
  28012. lastKnownAction = knownActionsForClip[knownActionsForClip.length - 1],
  28013. byClipCacheIndex = action._byClipCacheIndex
  28014. lastKnownAction._byClipCacheIndex = byClipCacheIndex
  28015. knownActionsForClip[byClipCacheIndex] = lastKnownAction
  28016. knownActionsForClip.pop()
  28017. action._byClipCacheIndex = null
  28018. const actionByRoot = actionsForClip.actionByRoot,
  28019. rootUuid = (action._localRoot || this._root).uuid
  28020. delete actionByRoot[rootUuid]
  28021. if (knownActionsForClip.length === 0) {
  28022. delete actionsByClip[clipUuid]
  28023. }
  28024. this._removeInactiveBindingsForAction(action)
  28025. }
  28026. _removeInactiveBindingsForAction(action) {
  28027. const bindings = action._propertyBindings
  28028. for (let i = 0, n = bindings.length; i !== n; ++i) {
  28029. const binding = bindings[i]
  28030. if (--binding.referenceCount === 0) {
  28031. this._removeInactiveBinding(binding)
  28032. }
  28033. }
  28034. }
  28035. _lendAction(action) {
  28036. // [ active actions | inactive actions ]
  28037. // [ active actions >| inactive actions ]
  28038. // s a
  28039. // <-swap->
  28040. // a s
  28041. const actions = this._actions,
  28042. prevIndex = action._cacheIndex,
  28043. lastActiveIndex = this._nActiveActions++,
  28044. firstInactiveAction = actions[lastActiveIndex]
  28045. action._cacheIndex = lastActiveIndex
  28046. actions[lastActiveIndex] = action
  28047. firstInactiveAction._cacheIndex = prevIndex
  28048. actions[prevIndex] = firstInactiveAction
  28049. }
  28050. _takeBackAction(action) {
  28051. // [ active actions | inactive actions ]
  28052. // [ active actions |< inactive actions ]
  28053. // a s
  28054. // <-swap->
  28055. // s a
  28056. const actions = this._actions,
  28057. prevIndex = action._cacheIndex,
  28058. firstInactiveIndex = --this._nActiveActions,
  28059. lastActiveAction = actions[firstInactiveIndex]
  28060. action._cacheIndex = firstInactiveIndex
  28061. actions[firstInactiveIndex] = action
  28062. lastActiveAction._cacheIndex = prevIndex
  28063. actions[prevIndex] = lastActiveAction
  28064. }
  28065. // Memory management for PropertyMixer objects
  28066. _addInactiveBinding(binding, rootUuid, trackName) {
  28067. const bindingsByRoot = this._bindingsByRootAndName,
  28068. bindings = this._bindings
  28069. let bindingByName = bindingsByRoot[rootUuid]
  28070. if (bindingByName === undefined) {
  28071. bindingByName = {}
  28072. bindingsByRoot[rootUuid] = bindingByName
  28073. }
  28074. bindingByName[trackName] = binding
  28075. binding._cacheIndex = bindings.length
  28076. bindings.push(binding)
  28077. }
  28078. _removeInactiveBinding(binding) {
  28079. const bindings = this._bindings,
  28080. propBinding = binding.binding,
  28081. rootUuid = propBinding.rootNode.uuid,
  28082. trackName = propBinding.path,
  28083. bindingsByRoot = this._bindingsByRootAndName,
  28084. bindingByName = bindingsByRoot[rootUuid],
  28085. lastInactiveBinding = bindings[bindings.length - 1],
  28086. cacheIndex = binding._cacheIndex
  28087. lastInactiveBinding._cacheIndex = cacheIndex
  28088. bindings[cacheIndex] = lastInactiveBinding
  28089. bindings.pop()
  28090. delete bindingByName[trackName]
  28091. if (Object.keys(bindingByName).length === 0) {
  28092. delete bindingsByRoot[rootUuid]
  28093. }
  28094. }
  28095. _lendBinding(binding) {
  28096. const bindings = this._bindings,
  28097. prevIndex = binding._cacheIndex,
  28098. lastActiveIndex = this._nActiveBindings++,
  28099. firstInactiveBinding = bindings[lastActiveIndex]
  28100. binding._cacheIndex = lastActiveIndex
  28101. bindings[lastActiveIndex] = binding
  28102. firstInactiveBinding._cacheIndex = prevIndex
  28103. bindings[prevIndex] = firstInactiveBinding
  28104. }
  28105. _takeBackBinding(binding) {
  28106. const bindings = this._bindings,
  28107. prevIndex = binding._cacheIndex,
  28108. firstInactiveIndex = --this._nActiveBindings,
  28109. lastActiveBinding = bindings[firstInactiveIndex]
  28110. binding._cacheIndex = firstInactiveIndex
  28111. bindings[firstInactiveIndex] = binding
  28112. lastActiveBinding._cacheIndex = prevIndex
  28113. bindings[prevIndex] = lastActiveBinding
  28114. }
  28115. // Memory management of Interpolants for weight and time scale
  28116. _lendControlInterpolant() {
  28117. const interpolants = this._controlInterpolants,
  28118. lastActiveIndex = this._nActiveControlInterpolants++
  28119. let interpolant = interpolants[lastActiveIndex]
  28120. if (interpolant === undefined) {
  28121. interpolant = new LinearInterpolant(new Float32Array(2), new Float32Array(2), 1, _controlInterpolantsResultBuffer)
  28122. interpolant.__cacheIndex = lastActiveIndex
  28123. interpolants[lastActiveIndex] = interpolant
  28124. }
  28125. return interpolant
  28126. }
  28127. _takeBackControlInterpolant(interpolant) {
  28128. const interpolants = this._controlInterpolants,
  28129. prevIndex = interpolant.__cacheIndex,
  28130. firstInactiveIndex = --this._nActiveControlInterpolants,
  28131. lastActiveInterpolant = interpolants[firstInactiveIndex]
  28132. interpolant.__cacheIndex = firstInactiveIndex
  28133. interpolants[firstInactiveIndex] = interpolant
  28134. lastActiveInterpolant.__cacheIndex = prevIndex
  28135. interpolants[prevIndex] = lastActiveInterpolant
  28136. }
  28137. // return an action for a clip optionally using a custom root target
  28138. // object (this method allocates a lot of dynamic memory in case a
  28139. // previously unknown clip/root combination is specified)
  28140. clipAction(clip, optionalRoot, blendMode) {
  28141. const root = optionalRoot || this._root,
  28142. rootUuid = root.uuid
  28143. let clipObject = typeof clip === 'string' ? AnimationClip.findByName(root, clip) : clip
  28144. const clipUuid = clipObject !== null ? clipObject.uuid : clip
  28145. const actionsForClip = this._actionsByClip[clipUuid]
  28146. let prototypeAction = null
  28147. if (blendMode === undefined) {
  28148. if (clipObject !== null) {
  28149. blendMode = clipObject.blendMode
  28150. } else {
  28151. blendMode = NormalAnimationBlendMode
  28152. }
  28153. }
  28154. if (actionsForClip !== undefined) {
  28155. const existingAction = actionsForClip.actionByRoot[rootUuid]
  28156. if (existingAction !== undefined && existingAction.blendMode === blendMode) {
  28157. return existingAction
  28158. }
  28159. // we know the clip, so we don't have to parse all
  28160. // the bindings again but can just copy
  28161. prototypeAction = actionsForClip.knownActions[0]
  28162. // also, take the clip from the prototype action
  28163. if (clipObject === null) clipObject = prototypeAction._clip
  28164. }
  28165. // clip must be known when specified via string
  28166. if (clipObject === null) return null
  28167. // allocate all resources required to run it
  28168. const newAction = new AnimationAction(this, clipObject, optionalRoot, blendMode)
  28169. this._bindAction(newAction, prototypeAction)
  28170. // and make the action known to the memory manager
  28171. this._addInactiveAction(newAction, clipUuid, rootUuid)
  28172. return newAction
  28173. }
  28174. // get an existing action
  28175. existingAction(clip, optionalRoot) {
  28176. const root = optionalRoot || this._root,
  28177. rootUuid = root.uuid,
  28178. clipObject = typeof clip === 'string' ? AnimationClip.findByName(root, clip) : clip,
  28179. clipUuid = clipObject ? clipObject.uuid : clip,
  28180. actionsForClip = this._actionsByClip[clipUuid]
  28181. if (actionsForClip !== undefined) {
  28182. return actionsForClip.actionByRoot[rootUuid] || null
  28183. }
  28184. return null
  28185. }
  28186. // deactivates all previously scheduled actions
  28187. stopAllAction() {
  28188. const actions = this._actions,
  28189. nActions = this._nActiveActions
  28190. for (let i = nActions - 1; i >= 0; --i) {
  28191. actions[i].stop()
  28192. }
  28193. return this
  28194. }
  28195. // advance the time and update apply the animation
  28196. update(deltaTime) {
  28197. deltaTime *= this.timeScale
  28198. const actions = this._actions,
  28199. nActions = this._nActiveActions,
  28200. time = (this.time += deltaTime),
  28201. timeDirection = Math.sign(deltaTime),
  28202. accuIndex = (this._accuIndex ^= 1)
  28203. // run active actions
  28204. for (let i = 0; i !== nActions; ++i) {
  28205. const action = actions[i]
  28206. action._update(time, deltaTime, timeDirection, accuIndex)
  28207. }
  28208. // update scene graph
  28209. const bindings = this._bindings,
  28210. nBindings = this._nActiveBindings
  28211. for (let i = 0; i !== nBindings; ++i) {
  28212. bindings[i].apply(accuIndex)
  28213. }
  28214. return this
  28215. }
  28216. // Allows you to seek to a specific time in an animation.
  28217. setTime(timeInSeconds) {
  28218. this.time = 0 // Zero out time attribute for AnimationMixer object;
  28219. for (let i = 0; i < this._actions.length; i++) {
  28220. this._actions[i].time = 0 // Zero out time attribute for all associated AnimationAction objects.
  28221. }
  28222. return this.update(timeInSeconds) // Update used to set exact time. Returns "this" AnimationMixer object.
  28223. }
  28224. // return this mixer's root target object
  28225. getRoot() {
  28226. return this._root
  28227. }
  28228. // free all resources specific to a particular clip
  28229. uncacheClip(clip) {
  28230. const actions = this._actions,
  28231. clipUuid = clip.uuid,
  28232. actionsByClip = this._actionsByClip,
  28233. actionsForClip = actionsByClip[clipUuid]
  28234. if (actionsForClip !== undefined) {
  28235. // note: just calling _removeInactiveAction would mess up the
  28236. // iteration state and also require updating the state we can
  28237. // just throw away
  28238. const actionsToRemove = actionsForClip.knownActions
  28239. for (let i = 0, n = actionsToRemove.length; i !== n; ++i) {
  28240. const action = actionsToRemove[i]
  28241. this._deactivateAction(action)
  28242. const cacheIndex = action._cacheIndex,
  28243. lastInactiveAction = actions[actions.length - 1]
  28244. action._cacheIndex = null
  28245. action._byClipCacheIndex = null
  28246. lastInactiveAction._cacheIndex = cacheIndex
  28247. actions[cacheIndex] = lastInactiveAction
  28248. actions.pop()
  28249. this._removeInactiveBindingsForAction(action)
  28250. }
  28251. delete actionsByClip[clipUuid]
  28252. }
  28253. }
  28254. // free all resources specific to a particular root target object
  28255. uncacheRoot(root) {
  28256. const rootUuid = root.uuid,
  28257. actionsByClip = this._actionsByClip
  28258. for (const clipUuid in actionsByClip) {
  28259. const actionByRoot = actionsByClip[clipUuid].actionByRoot,
  28260. action = actionByRoot[rootUuid]
  28261. if (action !== undefined) {
  28262. this._deactivateAction(action)
  28263. this._removeInactiveAction(action)
  28264. }
  28265. }
  28266. const bindingsByRoot = this._bindingsByRootAndName,
  28267. bindingByName = bindingsByRoot[rootUuid]
  28268. if (bindingByName !== undefined) {
  28269. for (const trackName in bindingByName) {
  28270. const binding = bindingByName[trackName]
  28271. binding.restoreOriginalState()
  28272. this._removeInactiveBinding(binding)
  28273. }
  28274. }
  28275. }
  28276. // remove a targeted clip from the cache
  28277. uncacheAction(clip, optionalRoot) {
  28278. const action = this.existingAction(clip, optionalRoot)
  28279. if (action !== null) {
  28280. this._deactivateAction(action)
  28281. this._removeInactiveAction(action)
  28282. }
  28283. }
  28284. }
  28285. class Uniform {
  28286. constructor(value) {
  28287. if (typeof value === 'string') {
  28288. console.warn('THREE.Uniform: Type parameter is no longer needed.')
  28289. value = arguments[1]
  28290. }
  28291. this.value = value
  28292. }
  28293. clone() {
  28294. return new Uniform(this.value.clone === undefined ? this.value : this.value.clone())
  28295. }
  28296. }
  28297. class InstancedInterleavedBuffer extends InterleavedBuffer {
  28298. constructor(array, stride, meshPerAttribute = 1) {
  28299. super(array, stride)
  28300. this.isInstancedInterleavedBuffer = true
  28301. this.meshPerAttribute = meshPerAttribute
  28302. }
  28303. copy(source) {
  28304. super.copy(source)
  28305. this.meshPerAttribute = source.meshPerAttribute
  28306. return this
  28307. }
  28308. clone(data) {
  28309. const ib = super.clone(data)
  28310. ib.meshPerAttribute = this.meshPerAttribute
  28311. return ib
  28312. }
  28313. toJSON(data) {
  28314. const json = super.toJSON(data)
  28315. json.isInstancedInterleavedBuffer = true
  28316. json.meshPerAttribute = this.meshPerAttribute
  28317. return json
  28318. }
  28319. }
  28320. class GLBufferAttribute {
  28321. constructor(buffer, type, itemSize, elementSize, count) {
  28322. this.isGLBufferAttribute = true
  28323. this.buffer = buffer
  28324. this.type = type
  28325. this.itemSize = itemSize
  28326. this.elementSize = elementSize
  28327. this.count = count
  28328. this.version = 0
  28329. }
  28330. set needsUpdate(value) {
  28331. if (value === true) this.version++
  28332. }
  28333. setBuffer(buffer) {
  28334. this.buffer = buffer
  28335. return this
  28336. }
  28337. setType(type, elementSize) {
  28338. this.type = type
  28339. this.elementSize = elementSize
  28340. return this
  28341. }
  28342. setItemSize(itemSize) {
  28343. this.itemSize = itemSize
  28344. return this
  28345. }
  28346. setCount(count) {
  28347. this.count = count
  28348. return this
  28349. }
  28350. }
  28351. class Raycaster {
  28352. constructor(origin, direction, near = 0, far = Infinity) {
  28353. this.ray = new Ray(origin, direction)
  28354. // direction is assumed to be normalized (for accurate distance calculations)
  28355. this.near = near
  28356. this.far = far
  28357. this.camera = null
  28358. this.layers = new Layers()
  28359. this.params = {
  28360. Mesh: {},
  28361. Line: { threshold: 1 },
  28362. LOD: {},
  28363. Points: { threshold: 1 },
  28364. Sprite: {}
  28365. }
  28366. }
  28367. set(origin, direction) {
  28368. // direction is assumed to be normalized (for accurate distance calculations)
  28369. this.ray.set(origin, direction)
  28370. }
  28371. setFromCamera(coords, camera) {
  28372. if (camera.isPerspectiveCamera) {
  28373. this.ray.origin.setFromMatrixPosition(camera.matrixWorld)
  28374. this.ray.direction
  28375. .set(coords.x, coords.y, 0.5)
  28376. .unproject(camera)
  28377. .sub(this.ray.origin)
  28378. .normalize()
  28379. this.camera = camera
  28380. } else if (camera.isOrthographicCamera) {
  28381. this.ray.origin.set(coords.x, coords.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera) // set origin in plane of camera
  28382. this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld)
  28383. this.camera = camera
  28384. } else {
  28385. console.error('THREE.Raycaster: Unsupported camera type: ' + camera.type)
  28386. }
  28387. }
  28388. intersectObject(object, recursive = true, intersects = []) {
  28389. intersectObject(object, this, intersects, recursive)
  28390. intersects.sort(ascSort)
  28391. return intersects
  28392. }
  28393. intersectObjects(objects, recursive = true, intersects = []) {
  28394. for (let i = 0, l = objects.length; i < l; i++) {
  28395. intersectObject(objects[i], this, intersects, recursive)
  28396. }
  28397. intersects.sort(ascSort)
  28398. return intersects
  28399. }
  28400. }
  28401. function ascSort(a, b) {
  28402. return a.distance - b.distance
  28403. }
  28404. function intersectObject(object, raycaster, intersects, recursive) {
  28405. if (object.layers.test(raycaster.layers)) {
  28406. object.raycast(raycaster, intersects)
  28407. }
  28408. if (recursive === true) {
  28409. const children = object.children
  28410. for (let i = 0, l = children.length; i < l; i++) {
  28411. intersectObject(children[i], raycaster, intersects, true)
  28412. }
  28413. }
  28414. }
  28415. /**
  28416. * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
  28417. *
  28418. * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
  28419. * The azimuthal angle (theta) is measured from the positive z-axis.
  28420. */
  28421. class Spherical {
  28422. constructor(radius = 1, phi = 0, theta = 0) {
  28423. this.radius = radius
  28424. this.phi = phi // polar angle
  28425. this.theta = theta // azimuthal angle
  28426. return this
  28427. }
  28428. set(radius, phi, theta) {
  28429. this.radius = radius
  28430. this.phi = phi
  28431. this.theta = theta
  28432. return this
  28433. }
  28434. copy(other) {
  28435. this.radius = other.radius
  28436. this.phi = other.phi
  28437. this.theta = other.theta
  28438. return this
  28439. }
  28440. // restrict phi to be between EPS and PI-EPS
  28441. makeSafe() {
  28442. const EPS = 0.000001
  28443. this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi))
  28444. return this
  28445. }
  28446. setFromVector3(v) {
  28447. return this.setFromCartesianCoords(v.x, v.y, v.z)
  28448. }
  28449. setFromCartesianCoords(x, y, z) {
  28450. this.radius = Math.sqrt(x * x + y * y + z * z)
  28451. if (this.radius === 0) {
  28452. this.theta = 0
  28453. this.phi = 0
  28454. } else {
  28455. this.theta = Math.atan2(x, z)
  28456. this.phi = Math.acos(clamp(y / this.radius, -1, 1))
  28457. }
  28458. return this
  28459. }
  28460. clone() {
  28461. return new this.constructor().copy(this)
  28462. }
  28463. }
  28464. /**
  28465. * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
  28466. */
  28467. class Cylindrical {
  28468. constructor(radius = 1, theta = 0, y = 0) {
  28469. this.radius = radius // distance from the origin to a point in the x-z plane
  28470. this.theta = theta // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
  28471. this.y = y // height above the x-z plane
  28472. return this
  28473. }
  28474. set(radius, theta, y) {
  28475. this.radius = radius
  28476. this.theta = theta
  28477. this.y = y
  28478. return this
  28479. }
  28480. copy(other) {
  28481. this.radius = other.radius
  28482. this.theta = other.theta
  28483. this.y = other.y
  28484. return this
  28485. }
  28486. setFromVector3(v) {
  28487. return this.setFromCartesianCoords(v.x, v.y, v.z)
  28488. }
  28489. setFromCartesianCoords(x, y, z) {
  28490. this.radius = Math.sqrt(x * x + z * z)
  28491. this.theta = Math.atan2(x, z)
  28492. this.y = y
  28493. return this
  28494. }
  28495. clone() {
  28496. return new this.constructor().copy(this)
  28497. }
  28498. }
  28499. const _vector$4 = /*@__PURE__*/ new Vector2()
  28500. class Box2 {
  28501. constructor(min = new Vector2(+Infinity, +Infinity), max = new Vector2(-Infinity, -Infinity)) {
  28502. this.isBox2 = true
  28503. this.min = min
  28504. this.max = max
  28505. }
  28506. set(min, max) {
  28507. this.min.copy(min)
  28508. this.max.copy(max)
  28509. return this
  28510. }
  28511. setFromPoints(points) {
  28512. this.makeEmpty()
  28513. for (let i = 0, il = points.length; i < il; i++) {
  28514. this.expandByPoint(points[i])
  28515. }
  28516. return this
  28517. }
  28518. setFromCenterAndSize(center, size) {
  28519. const halfSize = _vector$4.copy(size).multiplyScalar(0.5)
  28520. this.min.copy(center).sub(halfSize)
  28521. this.max.copy(center).add(halfSize)
  28522. return this
  28523. }
  28524. clone() {
  28525. return new this.constructor().copy(this)
  28526. }
  28527. copy(box) {
  28528. this.min.copy(box.min)
  28529. this.max.copy(box.max)
  28530. return this
  28531. }
  28532. makeEmpty() {
  28533. this.min.x = this.min.y = +Infinity
  28534. this.max.x = this.max.y = -Infinity
  28535. return this
  28536. }
  28537. isEmpty() {
  28538. // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
  28539. return this.max.x < this.min.x || this.max.y < this.min.y
  28540. }
  28541. getCenter(target) {
  28542. return this.isEmpty() ? target.set(0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5)
  28543. }
  28544. getSize(target) {
  28545. return this.isEmpty() ? target.set(0, 0) : target.subVectors(this.max, this.min)
  28546. }
  28547. expandByPoint(point) {
  28548. this.min.min(point)
  28549. this.max.max(point)
  28550. return this
  28551. }
  28552. expandByVector(vector) {
  28553. this.min.sub(vector)
  28554. this.max.add(vector)
  28555. return this
  28556. }
  28557. expandByScalar(scalar) {
  28558. this.min.addScalar(-scalar)
  28559. this.max.addScalar(scalar)
  28560. return this
  28561. }
  28562. containsPoint(point) {
  28563. return point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y ? false : true
  28564. }
  28565. containsBox(box) {
  28566. return this.min.x <= box.min.x && box.max.x <= this.max.x && this.min.y <= box.min.y && box.max.y <= this.max.y
  28567. }
  28568. getParameter(point, target) {
  28569. // This can potentially have a divide by zero if the box
  28570. // has a size dimension of 0.
  28571. return target.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y))
  28572. }
  28573. intersectsBox(box) {
  28574. // using 4 splitting planes to rule out intersections
  28575. return box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y ? false : true
  28576. }
  28577. clampPoint(point, target) {
  28578. return target.copy(point).clamp(this.min, this.max)
  28579. }
  28580. distanceToPoint(point) {
  28581. const clampedPoint = _vector$4.copy(point).clamp(this.min, this.max)
  28582. return clampedPoint.sub(point).length()
  28583. }
  28584. intersect(box) {
  28585. this.min.max(box.min)
  28586. this.max.min(box.max)
  28587. return this
  28588. }
  28589. union(box) {
  28590. this.min.min(box.min)
  28591. this.max.max(box.max)
  28592. return this
  28593. }
  28594. translate(offset) {
  28595. this.min.add(offset)
  28596. this.max.add(offset)
  28597. return this
  28598. }
  28599. equals(box) {
  28600. return box.min.equals(this.min) && box.max.equals(this.max)
  28601. }
  28602. }
  28603. const _startP = /*@__PURE__*/ new Vector3()
  28604. const _startEnd = /*@__PURE__*/ new Vector3()
  28605. class Line3 {
  28606. constructor(start = new Vector3(), end = new Vector3()) {
  28607. this.start = start
  28608. this.end = end
  28609. }
  28610. set(start, end) {
  28611. this.start.copy(start)
  28612. this.end.copy(end)
  28613. return this
  28614. }
  28615. copy(line) {
  28616. this.start.copy(line.start)
  28617. this.end.copy(line.end)
  28618. return this
  28619. }
  28620. getCenter(target) {
  28621. return target.addVectors(this.start, this.end).multiplyScalar(0.5)
  28622. }
  28623. delta(target) {
  28624. return target.subVectors(this.end, this.start)
  28625. }
  28626. distanceSq() {
  28627. return this.start.distanceToSquared(this.end)
  28628. }
  28629. distance() {
  28630. return this.start.distanceTo(this.end)
  28631. }
  28632. at(t, target) {
  28633. return this.delta(target)
  28634. .multiplyScalar(t)
  28635. .add(this.start)
  28636. }
  28637. closestPointToPointParameter(point, clampToLine) {
  28638. _startP.subVectors(point, this.start)
  28639. _startEnd.subVectors(this.end, this.start)
  28640. const startEnd2 = _startEnd.dot(_startEnd)
  28641. const startEnd_startP = _startEnd.dot(_startP)
  28642. let t = startEnd_startP / startEnd2
  28643. if (clampToLine) {
  28644. t = clamp(t, 0, 1)
  28645. }
  28646. return t
  28647. }
  28648. closestPointToPoint(point, clampToLine, target) {
  28649. const t = this.closestPointToPointParameter(point, clampToLine)
  28650. return this.delta(target)
  28651. .multiplyScalar(t)
  28652. .add(this.start)
  28653. }
  28654. applyMatrix4(matrix) {
  28655. this.start.applyMatrix4(matrix)
  28656. this.end.applyMatrix4(matrix)
  28657. return this
  28658. }
  28659. equals(line) {
  28660. return line.start.equals(this.start) && line.end.equals(this.end)
  28661. }
  28662. clone() {
  28663. return new this.constructor().copy(this)
  28664. }
  28665. }
  28666. const _vector$3 = /*@__PURE__*/ new Vector3()
  28667. class SpotLightHelper extends Object3D {
  28668. constructor(light, color) {
  28669. super()
  28670. this.light = light
  28671. this.light.updateMatrixWorld()
  28672. this.matrix = light.matrixWorld
  28673. this.matrixAutoUpdate = false
  28674. this.color = color
  28675. const geometry = new BufferGeometry()
  28676. const positions = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 1]
  28677. for (let i = 0, j = 1, l = 32; i < l; i++, j++) {
  28678. const p1 = (i / l) * Math.PI * 2
  28679. const p2 = (j / l) * Math.PI * 2
  28680. positions.push(Math.cos(p1), Math.sin(p1), 1, Math.cos(p2), Math.sin(p2), 1)
  28681. }
  28682. geometry.setAttribute('position', new Float32BufferAttribute(positions, 3))
  28683. const material = new LineBasicMaterial({ fog: false, toneMapped: false })
  28684. this.cone = new LineSegments(geometry, material)
  28685. this.add(this.cone)
  28686. this.update()
  28687. }
  28688. dispose() {
  28689. this.cone.geometry.dispose()
  28690. this.cone.material.dispose()
  28691. }
  28692. update() {
  28693. this.light.updateMatrixWorld()
  28694. const coneLength = this.light.distance ? this.light.distance : 1000
  28695. const coneWidth = coneLength * Math.tan(this.light.angle)
  28696. this.cone.scale.set(coneWidth, coneWidth, coneLength)
  28697. _vector$3.setFromMatrixPosition(this.light.target.matrixWorld)
  28698. this.cone.lookAt(_vector$3)
  28699. if (this.color !== undefined) {
  28700. this.cone.material.color.set(this.color)
  28701. } else {
  28702. this.cone.material.color.copy(this.light.color)
  28703. }
  28704. }
  28705. }
  28706. const _vector$2 = /*@__PURE__*/ new Vector3()
  28707. const _boneMatrix = /*@__PURE__*/ new Matrix4()
  28708. const _matrixWorldInv = /*@__PURE__*/ new Matrix4()
  28709. class SkeletonHelper extends LineSegments {
  28710. constructor(object) {
  28711. const bones = getBoneList(object)
  28712. const geometry = new BufferGeometry()
  28713. const vertices = []
  28714. const colors = []
  28715. const color1 = new Color(0, 0, 1)
  28716. const color2 = new Color(0, 1, 0)
  28717. for (let i = 0; i < bones.length; i++) {
  28718. const bone = bones[i]
  28719. if (bone.parent && bone.parent.isBone) {
  28720. vertices.push(0, 0, 0)
  28721. vertices.push(0, 0, 0)
  28722. colors.push(color1.r, color1.g, color1.b)
  28723. colors.push(color2.r, color2.g, color2.b)
  28724. }
  28725. }
  28726. geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  28727. geometry.setAttribute('color', new Float32BufferAttribute(colors, 3))
  28728. const material = new LineBasicMaterial({ vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true })
  28729. super(geometry, material)
  28730. this.isSkeletonHelper = true
  28731. this.type = 'SkeletonHelper'
  28732. this.root = object
  28733. this.bones = bones
  28734. this.matrix = object.matrixWorld
  28735. this.matrixAutoUpdate = false
  28736. }
  28737. updateMatrixWorld(force) {
  28738. const bones = this.bones
  28739. const geometry = this.geometry
  28740. const position = geometry.getAttribute('position')
  28741. _matrixWorldInv.copy(this.root.matrixWorld).invert()
  28742. for (let i = 0, j = 0; i < bones.length; i++) {
  28743. const bone = bones[i]
  28744. if (bone.parent && bone.parent.isBone) {
  28745. _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld)
  28746. _vector$2.setFromMatrixPosition(_boneMatrix)
  28747. position.setXYZ(j, _vector$2.x, _vector$2.y, _vector$2.z)
  28748. _boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld)
  28749. _vector$2.setFromMatrixPosition(_boneMatrix)
  28750. position.setXYZ(j + 1, _vector$2.x, _vector$2.y, _vector$2.z)
  28751. j += 2
  28752. }
  28753. }
  28754. geometry.getAttribute('position').needsUpdate = true
  28755. super.updateMatrixWorld(force)
  28756. }
  28757. }
  28758. function getBoneList(object) {
  28759. const boneList = []
  28760. if (object.isBone === true) {
  28761. boneList.push(object)
  28762. }
  28763. for (let i = 0; i < object.children.length; i++) {
  28764. boneList.push.apply(boneList, getBoneList(object.children[i]))
  28765. }
  28766. return boneList
  28767. }
  28768. class PointLightHelper extends Mesh {
  28769. constructor(light, sphereSize, color) {
  28770. const geometry = new SphereGeometry(sphereSize, 4, 2)
  28771. const material = new MeshBasicMaterial({ wireframe: true, fog: false, toneMapped: false })
  28772. super(geometry, material)
  28773. this.light = light
  28774. this.light.updateMatrixWorld()
  28775. this.color = color
  28776. this.type = 'PointLightHelper'
  28777. this.matrix = this.light.matrixWorld
  28778. this.matrixAutoUpdate = false
  28779. this.update()
  28780. /*
  28781. // TODO: delete this comment?
  28782. const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
  28783. const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
  28784. this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
  28785. this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
  28786. const d = light.distance;
  28787. if ( d === 0.0 ) {
  28788. this.lightDistance.visible = false;
  28789. } else {
  28790. this.lightDistance.scale.set( d, d, d );
  28791. }
  28792. this.add( this.lightDistance );
  28793. */
  28794. }
  28795. dispose() {
  28796. this.geometry.dispose()
  28797. this.material.dispose()
  28798. }
  28799. update() {
  28800. if (this.color !== undefined) {
  28801. this.material.color.set(this.color)
  28802. } else {
  28803. this.material.color.copy(this.light.color)
  28804. }
  28805. /*
  28806. const d = this.light.distance;
  28807. if ( d === 0.0 ) {
  28808. this.lightDistance.visible = false;
  28809. } else {
  28810. this.lightDistance.visible = true;
  28811. this.lightDistance.scale.set( d, d, d );
  28812. }
  28813. */
  28814. }
  28815. }
  28816. const _vector$1 = /*@__PURE__*/ new Vector3()
  28817. const _color1 = /*@__PURE__*/ new Color()
  28818. const _color2 = /*@__PURE__*/ new Color()
  28819. class HemisphereLightHelper extends Object3D {
  28820. constructor(light, size, color) {
  28821. super()
  28822. this.light = light
  28823. this.light.updateMatrixWorld()
  28824. this.matrix = light.matrixWorld
  28825. this.matrixAutoUpdate = false
  28826. this.color = color
  28827. const geometry = new OctahedronGeometry(size)
  28828. geometry.rotateY(Math.PI * 0.5)
  28829. this.material = new MeshBasicMaterial({ wireframe: true, fog: false, toneMapped: false })
  28830. if (this.color === undefined) this.material.vertexColors = true
  28831. const position = geometry.getAttribute('position')
  28832. const colors = new Float32Array(position.count * 3)
  28833. geometry.setAttribute('color', new BufferAttribute(colors, 3))
  28834. this.add(new Mesh(geometry, this.material))
  28835. this.update()
  28836. }
  28837. dispose() {
  28838. this.children[0].geometry.dispose()
  28839. this.children[0].material.dispose()
  28840. }
  28841. update() {
  28842. const mesh = this.children[0]
  28843. if (this.color !== undefined) {
  28844. this.material.color.set(this.color)
  28845. } else {
  28846. const colors = mesh.geometry.getAttribute('color')
  28847. _color1.copy(this.light.color)
  28848. _color2.copy(this.light.groundColor)
  28849. for (let i = 0, l = colors.count; i < l; i++) {
  28850. const color = i < l / 2 ? _color1 : _color2
  28851. colors.setXYZ(i, color.r, color.g, color.b)
  28852. }
  28853. colors.needsUpdate = true
  28854. }
  28855. mesh.lookAt(_vector$1.setFromMatrixPosition(this.light.matrixWorld).negate())
  28856. }
  28857. }
  28858. class GridHelper extends LineSegments {
  28859. constructor(size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888) {
  28860. color1 = new Color(color1)
  28861. color2 = new Color(color2)
  28862. const center = divisions / 2
  28863. const step = size / divisions
  28864. const halfSize = size / 2
  28865. const vertices = [],
  28866. colors = []
  28867. for (let i = 0, j = 0, k = -halfSize; i <= divisions; i++, k += step) {
  28868. vertices.push(-halfSize, 0, k, halfSize, 0, k)
  28869. vertices.push(k, 0, -halfSize, k, 0, halfSize)
  28870. const color = i === center ? color1 : color2
  28871. color.toArray(colors, j)
  28872. j += 3
  28873. color.toArray(colors, j)
  28874. j += 3
  28875. color.toArray(colors, j)
  28876. j += 3
  28877. color.toArray(colors, j)
  28878. j += 3
  28879. }
  28880. const geometry = new BufferGeometry()
  28881. geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  28882. geometry.setAttribute('color', new Float32BufferAttribute(colors, 3))
  28883. const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false })
  28884. super(geometry, material)
  28885. this.type = 'GridHelper'
  28886. }
  28887. }
  28888. class PolarGridHelper extends LineSegments {
  28889. constructor(radius = 10, radials = 16, circles = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888) {
  28890. color1 = new Color(color1)
  28891. color2 = new Color(color2)
  28892. const vertices = []
  28893. const colors = []
  28894. // create the radials
  28895. for (let i = 0; i <= radials; i++) {
  28896. const v = (i / radials) * (Math.PI * 2)
  28897. const x = Math.sin(v) * radius
  28898. const z = Math.cos(v) * radius
  28899. vertices.push(0, 0, 0)
  28900. vertices.push(x, 0, z)
  28901. const color = i & 1 ? color1 : color2
  28902. colors.push(color.r, color.g, color.b)
  28903. colors.push(color.r, color.g, color.b)
  28904. }
  28905. // create the circles
  28906. for (let i = 0; i <= circles; i++) {
  28907. const color = i & 1 ? color1 : color2
  28908. const r = radius - (radius / circles) * i
  28909. for (let j = 0; j < divisions; j++) {
  28910. // first vertex
  28911. let v = (j / divisions) * (Math.PI * 2)
  28912. let x = Math.sin(v) * r
  28913. let z = Math.cos(v) * r
  28914. vertices.push(x, 0, z)
  28915. colors.push(color.r, color.g, color.b)
  28916. // second vertex
  28917. v = ((j + 1) / divisions) * (Math.PI * 2)
  28918. x = Math.sin(v) * r
  28919. z = Math.cos(v) * r
  28920. vertices.push(x, 0, z)
  28921. colors.push(color.r, color.g, color.b)
  28922. }
  28923. }
  28924. const geometry = new BufferGeometry()
  28925. geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  28926. geometry.setAttribute('color', new Float32BufferAttribute(colors, 3))
  28927. const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false })
  28928. super(geometry, material)
  28929. this.type = 'PolarGridHelper'
  28930. }
  28931. }
  28932. const _v1 = /*@__PURE__*/ new Vector3()
  28933. const _v2 = /*@__PURE__*/ new Vector3()
  28934. const _v3 = /*@__PURE__*/ new Vector3()
  28935. class DirectionalLightHelper extends Object3D {
  28936. constructor(light, size, color) {
  28937. super()
  28938. this.light = light
  28939. this.light.updateMatrixWorld()
  28940. this.matrix = light.matrixWorld
  28941. this.matrixAutoUpdate = false
  28942. this.color = color
  28943. if (size === undefined) size = 1
  28944. let geometry = new BufferGeometry()
  28945. geometry.setAttribute('position', new Float32BufferAttribute([-size, size, 0, size, size, 0, size, -size, 0, -size, -size, 0, -size, size, 0], 3))
  28946. const material = new LineBasicMaterial({ fog: false, toneMapped: false })
  28947. this.lightPlane = new Line(geometry, material)
  28948. this.add(this.lightPlane)
  28949. geometry = new BufferGeometry()
  28950. geometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 0, 1], 3))
  28951. this.targetLine = new Line(geometry, material)
  28952. this.add(this.targetLine)
  28953. this.update()
  28954. }
  28955. dispose() {
  28956. this.lightPlane.geometry.dispose()
  28957. this.lightPlane.material.dispose()
  28958. this.targetLine.geometry.dispose()
  28959. this.targetLine.material.dispose()
  28960. }
  28961. update() {
  28962. _v1.setFromMatrixPosition(this.light.matrixWorld)
  28963. _v2.setFromMatrixPosition(this.light.target.matrixWorld)
  28964. _v3.subVectors(_v2, _v1)
  28965. this.lightPlane.lookAt(_v2)
  28966. if (this.color !== undefined) {
  28967. this.lightPlane.material.color.set(this.color)
  28968. this.targetLine.material.color.set(this.color)
  28969. } else {
  28970. this.lightPlane.material.color.copy(this.light.color)
  28971. this.targetLine.material.color.copy(this.light.color)
  28972. }
  28973. this.targetLine.lookAt(_v2)
  28974. this.targetLine.scale.z = _v3.length()
  28975. }
  28976. }
  28977. const _vector = /*@__PURE__*/ new Vector3()
  28978. const _camera = /*@__PURE__*/ new Camera()
  28979. /**
  28980. * - shows frustum, line of sight and up of the camera
  28981. * - suitable for fast updates
  28982. * - based on frustum visualization in lightgl.js shadowmap example
  28983. * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html
  28984. */
  28985. class CameraHelper extends LineSegments {
  28986. constructor(camera) {
  28987. const geometry = new BufferGeometry()
  28988. const material = new LineBasicMaterial({ color: 0xffffff, vertexColors: true, toneMapped: false })
  28989. const vertices = []
  28990. const colors = []
  28991. const pointMap = {}
  28992. // colors
  28993. const colorFrustum = new Color(0xffaa00)
  28994. const colorCone = new Color(0xff0000)
  28995. const colorUp = new Color(0x00aaff)
  28996. const colorTarget = new Color(0xffffff)
  28997. const colorCross = new Color(0x333333)
  28998. // near
  28999. addLine('n1', 'n2', colorFrustum)
  29000. addLine('n2', 'n4', colorFrustum)
  29001. addLine('n4', 'n3', colorFrustum)
  29002. addLine('n3', 'n1', colorFrustum)
  29003. // far
  29004. addLine('f1', 'f2', colorFrustum)
  29005. addLine('f2', 'f4', colorFrustum)
  29006. addLine('f4', 'f3', colorFrustum)
  29007. addLine('f3', 'f1', colorFrustum)
  29008. // sides
  29009. addLine('n1', 'f1', colorFrustum)
  29010. addLine('n2', 'f2', colorFrustum)
  29011. addLine('n3', 'f3', colorFrustum)
  29012. addLine('n4', 'f4', colorFrustum)
  29013. // cone
  29014. addLine('p', 'n1', colorCone)
  29015. addLine('p', 'n2', colorCone)
  29016. addLine('p', 'n3', colorCone)
  29017. addLine('p', 'n4', colorCone)
  29018. // up
  29019. addLine('u1', 'u2', colorUp)
  29020. addLine('u2', 'u3', colorUp)
  29021. addLine('u3', 'u1', colorUp)
  29022. // target
  29023. addLine('c', 't', colorTarget)
  29024. addLine('p', 'c', colorCross)
  29025. // cross
  29026. addLine('cn1', 'cn2', colorCross)
  29027. addLine('cn3', 'cn4', colorCross)
  29028. addLine('cf1', 'cf2', colorCross)
  29029. addLine('cf3', 'cf4', colorCross)
  29030. function addLine(a, b, color) {
  29031. addPoint(a, color)
  29032. addPoint(b, color)
  29033. }
  29034. function addPoint(id, color) {
  29035. vertices.push(0, 0, 0)
  29036. colors.push(color.r, color.g, color.b)
  29037. if (pointMap[id] === undefined) {
  29038. pointMap[id] = []
  29039. }
  29040. pointMap[id].push(vertices.length / 3 - 1)
  29041. }
  29042. geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  29043. geometry.setAttribute('color', new Float32BufferAttribute(colors, 3))
  29044. super(geometry, material)
  29045. this.type = 'CameraHelper'
  29046. this.camera = camera
  29047. if (this.camera.updateProjectionMatrix) this.camera.updateProjectionMatrix()
  29048. this.matrix = camera.matrixWorld
  29049. this.matrixAutoUpdate = false
  29050. this.pointMap = pointMap
  29051. this.update()
  29052. }
  29053. update() {
  29054. const geometry = this.geometry
  29055. const pointMap = this.pointMap
  29056. const w = 1,
  29057. h = 1
  29058. // we need just camera projection matrix inverse
  29059. // world matrix must be identity
  29060. _camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse)
  29061. // center / target
  29062. setPoint('c', pointMap, geometry, _camera, 0, 0, -1)
  29063. setPoint('t', pointMap, geometry, _camera, 0, 0, 1)
  29064. // near
  29065. setPoint('n1', pointMap, geometry, _camera, -w, -h, -1)
  29066. setPoint('n2', pointMap, geometry, _camera, w, -h, -1)
  29067. setPoint('n3', pointMap, geometry, _camera, -w, h, -1)
  29068. setPoint('n4', pointMap, geometry, _camera, w, h, -1)
  29069. // far
  29070. setPoint('f1', pointMap, geometry, _camera, -w, -h, 1)
  29071. setPoint('f2', pointMap, geometry, _camera, w, -h, 1)
  29072. setPoint('f3', pointMap, geometry, _camera, -w, h, 1)
  29073. setPoint('f4', pointMap, geometry, _camera, w, h, 1)
  29074. // up
  29075. setPoint('u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, -1)
  29076. setPoint('u2', pointMap, geometry, _camera, -w * 0.7, h * 1.1, -1)
  29077. setPoint('u3', pointMap, geometry, _camera, 0, h * 2, -1)
  29078. // cross
  29079. setPoint('cf1', pointMap, geometry, _camera, -w, 0, 1)
  29080. setPoint('cf2', pointMap, geometry, _camera, w, 0, 1)
  29081. setPoint('cf3', pointMap, geometry, _camera, 0, -h, 1)
  29082. setPoint('cf4', pointMap, geometry, _camera, 0, h, 1)
  29083. setPoint('cn1', pointMap, geometry, _camera, -w, 0, -1)
  29084. setPoint('cn2', pointMap, geometry, _camera, w, 0, -1)
  29085. setPoint('cn3', pointMap, geometry, _camera, 0, -h, -1)
  29086. setPoint('cn4', pointMap, geometry, _camera, 0, h, -1)
  29087. geometry.getAttribute('position').needsUpdate = true
  29088. }
  29089. dispose() {
  29090. this.geometry.dispose()
  29091. this.material.dispose()
  29092. }
  29093. }
  29094. function setPoint(point, pointMap, geometry, camera, x, y, z) {
  29095. _vector.set(x, y, z).unproject(camera)
  29096. const points = pointMap[point]
  29097. if (points !== undefined) {
  29098. const position = geometry.getAttribute('position')
  29099. for (let i = 0, l = points.length; i < l; i++) {
  29100. position.setXYZ(points[i], _vector.x, _vector.y, _vector.z)
  29101. }
  29102. }
  29103. }
  29104. const _box = /*@__PURE__*/ new Box3()
  29105. class BoxHelper extends LineSegments {
  29106. constructor(object, color = 0xffff00) {
  29107. const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7])
  29108. const positions = new Float32Array(8 * 3)
  29109. const geometry = new BufferGeometry()
  29110. geometry.setIndex(new BufferAttribute(indices, 1))
  29111. geometry.setAttribute('position', new BufferAttribute(positions, 3))
  29112. super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }))
  29113. this.object = object
  29114. this.type = 'BoxHelper'
  29115. this.matrixAutoUpdate = false
  29116. this.update()
  29117. }
  29118. update(object) {
  29119. if (object !== undefined) {
  29120. console.warn('THREE.BoxHelper: .update() has no longer arguments.')
  29121. }
  29122. if (this.object !== undefined) {
  29123. _box.setFromObject(this.object)
  29124. }
  29125. if (_box.isEmpty()) return
  29126. const min = _box.min
  29127. const max = _box.max
  29128. /*
  29129. 5____4
  29130. 1/___0/|
  29131. | 6__|_7
  29132. 2/___3/
  29133. 0: max.x, max.y, max.z
  29134. 1: min.x, max.y, max.z
  29135. 2: min.x, min.y, max.z
  29136. 3: max.x, min.y, max.z
  29137. 4: max.x, max.y, min.z
  29138. 5: min.x, max.y, min.z
  29139. 6: min.x, min.y, min.z
  29140. 7: max.x, min.y, min.z
  29141. */
  29142. const position = this.geometry.attributes.position
  29143. const array = position.array
  29144. array[0] = max.x
  29145. array[1] = max.y
  29146. array[2] = max.z
  29147. array[3] = min.x
  29148. array[4] = max.y
  29149. array[5] = max.z
  29150. array[6] = min.x
  29151. array[7] = min.y
  29152. array[8] = max.z
  29153. array[9] = max.x
  29154. array[10] = min.y
  29155. array[11] = max.z
  29156. array[12] = max.x
  29157. array[13] = max.y
  29158. array[14] = min.z
  29159. array[15] = min.x
  29160. array[16] = max.y
  29161. array[17] = min.z
  29162. array[18] = min.x
  29163. array[19] = min.y
  29164. array[20] = min.z
  29165. array[21] = max.x
  29166. array[22] = min.y
  29167. array[23] = min.z
  29168. position.needsUpdate = true
  29169. this.geometry.computeBoundingSphere()
  29170. }
  29171. setFromObject(object) {
  29172. this.object = object
  29173. this.update()
  29174. return this
  29175. }
  29176. copy(source, recursive) {
  29177. super.copy(source, recursive)
  29178. this.object = source.object
  29179. return this
  29180. }
  29181. }
  29182. class Box3Helper extends LineSegments {
  29183. constructor(box, color = 0xffff00) {
  29184. const indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7])
  29185. const positions = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1]
  29186. const geometry = new BufferGeometry()
  29187. geometry.setIndex(new BufferAttribute(indices, 1))
  29188. geometry.setAttribute('position', new Float32BufferAttribute(positions, 3))
  29189. super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }))
  29190. this.box = box
  29191. this.type = 'Box3Helper'
  29192. this.geometry.computeBoundingSphere()
  29193. }
  29194. updateMatrixWorld(force) {
  29195. const box = this.box
  29196. if (box.isEmpty()) return
  29197. box.getCenter(this.position)
  29198. box.getSize(this.scale)
  29199. this.scale.multiplyScalar(0.5)
  29200. super.updateMatrixWorld(force)
  29201. }
  29202. }
  29203. class PlaneHelper extends Line {
  29204. constructor(plane, size = 1, hex = 0xffff00) {
  29205. const color = hex
  29206. const positions = [1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0]
  29207. const geometry = new BufferGeometry()
  29208. geometry.setAttribute('position', new Float32BufferAttribute(positions, 3))
  29209. geometry.computeBoundingSphere()
  29210. super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }))
  29211. this.type = 'PlaneHelper'
  29212. this.plane = plane
  29213. this.size = size
  29214. const positions2 = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1]
  29215. const geometry2 = new BufferGeometry()
  29216. geometry2.setAttribute('position', new Float32BufferAttribute(positions2, 3))
  29217. geometry2.computeBoundingSphere()
  29218. this.add(new Mesh(geometry2, new MeshBasicMaterial({ color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false })))
  29219. }
  29220. updateMatrixWorld(force) {
  29221. let scale = -this.plane.constant
  29222. if (Math.abs(scale) < 1e-8) scale = 1e-8 // sign does not matter
  29223. this.scale.set(0.5 * this.size, 0.5 * this.size, scale)
  29224. this.children[0].material.side = scale < 0 ? BackSide : FrontSide // renderer flips side when determinant < 0; flipping not wanted here
  29225. this.lookAt(this.plane.normal)
  29226. super.updateMatrixWorld(force)
  29227. }
  29228. }
  29229. const _axis = /*@__PURE__*/ new Vector3()
  29230. let _lineGeometry, _coneGeometry
  29231. class ArrowHelper extends Object3D {
  29232. // dir is assumed to be normalized
  29233. constructor(dir = new Vector3(0, 0, 1), origin = new Vector3(0, 0, 0), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2) {
  29234. super()
  29235. this.type = 'ArrowHelper'
  29236. if (_lineGeometry === undefined) {
  29237. _lineGeometry = new BufferGeometry()
  29238. _lineGeometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3))
  29239. _coneGeometry = new CylinderGeometry(0, 0.5, 1, 5, 1)
  29240. _coneGeometry.translate(0, -0.5, 0)
  29241. }
  29242. this.position.copy(origin)
  29243. this.line = new Line(_lineGeometry, new LineBasicMaterial({ color: color, toneMapped: false }))
  29244. this.line.matrixAutoUpdate = false
  29245. this.add(this.line)
  29246. this.cone = new Mesh(_coneGeometry, new MeshBasicMaterial({ color: color, toneMapped: false }))
  29247. this.cone.matrixAutoUpdate = false
  29248. this.add(this.cone)
  29249. this.setDirection(dir)
  29250. this.setLength(length, headLength, headWidth)
  29251. }
  29252. setDirection(dir) {
  29253. // dir is assumed to be normalized
  29254. if (dir.y > 0.99999) {
  29255. this.quaternion.set(0, 0, 0, 1)
  29256. } else if (dir.y < -0.99999) {
  29257. this.quaternion.set(1, 0, 0, 0)
  29258. } else {
  29259. _axis.set(dir.z, 0, -dir.x).normalize()
  29260. const radians = Math.acos(dir.y)
  29261. this.quaternion.setFromAxisAngle(_axis, radians)
  29262. }
  29263. }
  29264. setLength(length, headLength = length * 0.2, headWidth = headLength * 0.2) {
  29265. this.line.scale.set(1, Math.max(0.0001, length - headLength), 1) // see #17458
  29266. this.line.updateMatrix()
  29267. this.cone.scale.set(headWidth, headLength, headWidth)
  29268. this.cone.position.y = length
  29269. this.cone.updateMatrix()
  29270. }
  29271. setColor(color) {
  29272. this.line.material.color.set(color)
  29273. this.cone.material.color.set(color)
  29274. }
  29275. copy(source) {
  29276. super.copy(source, false)
  29277. this.line.copy(source.line)
  29278. this.cone.copy(source.cone)
  29279. return this
  29280. }
  29281. }
  29282. class AxesHelper extends LineSegments {
  29283. constructor(size = 1) {
  29284. const vertices = [0, 0, 0, size, 0, 0, 0, 0, 0, 0, size, 0, 0, 0, 0, 0, 0, size]
  29285. const colors = [1, 0, 0, 1, 0.6, 0, 0, 1, 0, 0.6, 1, 0, 0, 0, 1, 0, 0.6, 1]
  29286. const geometry = new BufferGeometry()
  29287. geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3))
  29288. geometry.setAttribute('color', new Float32BufferAttribute(colors, 3))
  29289. const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false })
  29290. super(geometry, material)
  29291. this.type = 'AxesHelper'
  29292. }
  29293. setColors(xAxisColor, yAxisColor, zAxisColor) {
  29294. const color = new Color()
  29295. const array = this.geometry.attributes.color.array
  29296. color.set(xAxisColor)
  29297. color.toArray(array, 0)
  29298. color.toArray(array, 3)
  29299. color.set(yAxisColor)
  29300. color.toArray(array, 6)
  29301. color.toArray(array, 9)
  29302. color.set(zAxisColor)
  29303. color.toArray(array, 12)
  29304. color.toArray(array, 15)
  29305. this.geometry.attributes.color.needsUpdate = true
  29306. return this
  29307. }
  29308. dispose() {
  29309. this.geometry.dispose()
  29310. this.material.dispose()
  29311. }
  29312. }
  29313. class ShapePath {
  29314. constructor() {
  29315. this.type = 'ShapePath'
  29316. this.color = new Color()
  29317. this.subPaths = []
  29318. this.currentPath = null
  29319. }
  29320. moveTo(x, y) {
  29321. this.currentPath = new Path()
  29322. this.subPaths.push(this.currentPath)
  29323. this.currentPath.moveTo(x, y)
  29324. return this
  29325. }
  29326. lineTo(x, y) {
  29327. this.currentPath.lineTo(x, y)
  29328. return this
  29329. }
  29330. quadraticCurveTo(aCPx, aCPy, aX, aY) {
  29331. this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY)
  29332. return this
  29333. }
  29334. bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
  29335. this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY)
  29336. return this
  29337. }
  29338. splineThru(pts) {
  29339. this.currentPath.splineThru(pts)
  29340. return this
  29341. }
  29342. toShapes(isCCW, noHoles) {
  29343. function toShapesNoHoles(inSubpaths) {
  29344. const shapes = []
  29345. for (let i = 0, l = inSubpaths.length; i < l; i++) {
  29346. const tmpPath = inSubpaths[i]
  29347. const tmpShape = new Shape()
  29348. tmpShape.curves = tmpPath.curves
  29349. shapes.push(tmpShape)
  29350. }
  29351. return shapes
  29352. }
  29353. function isPointInsidePolygon(inPt, inPolygon) {
  29354. const polyLen = inPolygon.length
  29355. // inPt on polygon contour => immediate success or
  29356. // toggling of inside/outside at every single! intersection point of an edge
  29357. // with the horizontal line through inPt, left of inPt
  29358. // not counting lowerY endpoints of edges and whole edges on that line
  29359. let inside = false
  29360. for (let p = polyLen - 1, q = 0; q < polyLen; p = q++) {
  29361. let edgeLowPt = inPolygon[p]
  29362. let edgeHighPt = inPolygon[q]
  29363. let edgeDx = edgeHighPt.x - edgeLowPt.x
  29364. let edgeDy = edgeHighPt.y - edgeLowPt.y
  29365. if (Math.abs(edgeDy) > Number.EPSILON) {
  29366. // not parallel
  29367. if (edgeDy < 0) {
  29368. edgeLowPt = inPolygon[q]
  29369. edgeDx = -edgeDx
  29370. edgeHighPt = inPolygon[p]
  29371. edgeDy = -edgeDy
  29372. }
  29373. if (inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y) continue
  29374. if (inPt.y === edgeLowPt.y) {
  29375. if (inPt.x === edgeLowPt.x) return true // inPt is on contour ?
  29376. // continue; // no intersection or edgeLowPt => doesn't count !!!
  29377. } else {
  29378. const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y)
  29379. if (perpEdge === 0) return true // inPt is on contour ?
  29380. if (perpEdge < 0) continue
  29381. inside = !inside // true intersection left of inPt
  29382. }
  29383. } else {
  29384. // parallel or collinear
  29385. if (inPt.y !== edgeLowPt.y) continue // parallel
  29386. // edge lies on the same horizontal line as inPt
  29387. if ((edgeHighPt.x <= inPt.x && inPt.x <= edgeLowPt.x) || (edgeLowPt.x <= inPt.x && inPt.x <= edgeHighPt.x)) return true // inPt: Point on contour !
  29388. // continue;
  29389. }
  29390. }
  29391. return inside
  29392. }
  29393. const isClockWise = ShapeUtils.isClockWise
  29394. const subPaths = this.subPaths
  29395. if (subPaths.length === 0) return []
  29396. if (noHoles === true) return toShapesNoHoles(subPaths)
  29397. let solid, tmpPath, tmpShape
  29398. const shapes = []
  29399. if (subPaths.length === 1) {
  29400. tmpPath = subPaths[0]
  29401. tmpShape = new Shape()
  29402. tmpShape.curves = tmpPath.curves
  29403. shapes.push(tmpShape)
  29404. return shapes
  29405. }
  29406. let holesFirst = !isClockWise(subPaths[0].getPoints())
  29407. holesFirst = isCCW ? !holesFirst : holesFirst
  29408. // console.log("Holes first", holesFirst);
  29409. const betterShapeHoles = []
  29410. const newShapes = []
  29411. let newShapeHoles = []
  29412. let mainIdx = 0
  29413. let tmpPoints
  29414. newShapes[mainIdx] = undefined
  29415. newShapeHoles[mainIdx] = []
  29416. for (let i = 0, l = subPaths.length; i < l; i++) {
  29417. tmpPath = subPaths[i]
  29418. tmpPoints = tmpPath.getPoints()
  29419. solid = isClockWise(tmpPoints)
  29420. solid = isCCW ? !solid : solid
  29421. if (solid) {
  29422. if (!holesFirst && newShapes[mainIdx]) mainIdx++
  29423. newShapes[mainIdx] = { s: new Shape(), p: tmpPoints }
  29424. newShapes[mainIdx].s.curves = tmpPath.curves
  29425. if (holesFirst) mainIdx++
  29426. newShapeHoles[mainIdx] = []
  29427. //console.log('cw', i);
  29428. } else {
  29429. newShapeHoles[mainIdx].push({ h: tmpPath, p: tmpPoints[0] })
  29430. //console.log('ccw', i);
  29431. }
  29432. }
  29433. // only Holes? -> probably all Shapes with wrong orientation
  29434. if (!newShapes[0]) return toShapesNoHoles(subPaths)
  29435. if (newShapes.length > 1) {
  29436. let ambiguous = false
  29437. let toChange = 0
  29438. for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
  29439. betterShapeHoles[sIdx] = []
  29440. }
  29441. for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
  29442. const sho = newShapeHoles[sIdx]
  29443. for (let hIdx = 0; hIdx < sho.length; hIdx++) {
  29444. const ho = sho[hIdx]
  29445. let hole_unassigned = true
  29446. for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
  29447. if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
  29448. if (sIdx !== s2Idx) toChange++
  29449. if (hole_unassigned) {
  29450. hole_unassigned = false
  29451. betterShapeHoles[s2Idx].push(ho)
  29452. } else {
  29453. ambiguous = true
  29454. }
  29455. }
  29456. }
  29457. if (hole_unassigned) {
  29458. betterShapeHoles[sIdx].push(ho)
  29459. }
  29460. }
  29461. }
  29462. if (toChange > 0 && ambiguous === false) {
  29463. newShapeHoles = betterShapeHoles
  29464. }
  29465. }
  29466. let tmpHoles
  29467. for (let i = 0, il = newShapes.length; i < il; i++) {
  29468. tmpShape = newShapes[i].s
  29469. shapes.push(tmpShape)
  29470. tmpHoles = newShapeHoles[i]
  29471. for (let j = 0, jl = tmpHoles.length; j < jl; j++) {
  29472. tmpShape.holes.push(tmpHoles[j].h)
  29473. }
  29474. }
  29475. //console.log("shape", shapes);
  29476. return shapes
  29477. }
  29478. }
  29479. // Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
  29480. class DataUtils {
  29481. // float32 to float16
  29482. static toHalfFloat(val) {
  29483. if (Math.abs(val) > 65504) console.warn('THREE.DataUtils.toHalfFloat(): Value out of range.')
  29484. val = clamp(val, -65504, 65504)
  29485. _floatView[0] = val
  29486. const f = _uint32View[0]
  29487. const e = (f >> 23) & 0x1ff
  29488. return _baseTable[e] + ((f & 0x007fffff) >> _shiftTable[e])
  29489. }
  29490. // float16 to float32
  29491. static fromHalfFloat(val) {
  29492. const m = val >> 10
  29493. _uint32View[0] = _mantissaTable[_offsetTable[m] + (val & 0x3ff)] + _exponentTable[m]
  29494. return _floatView[0]
  29495. }
  29496. }
  29497. // float32 to float16 helpers
  29498. const _buffer = new ArrayBuffer(4)
  29499. const _floatView = new Float32Array(_buffer)
  29500. const _uint32View = new Uint32Array(_buffer)
  29501. const _baseTable = new Uint32Array(512)
  29502. const _shiftTable = new Uint32Array(512)
  29503. for (let i = 0; i < 256; ++i) {
  29504. const e = i - 127
  29505. // very small number (0, -0)
  29506. if (e < -27) {
  29507. _baseTable[i] = 0x0000
  29508. _baseTable[i | 0x100] = 0x8000
  29509. _shiftTable[i] = 24
  29510. _shiftTable[i | 0x100] = 24
  29511. // small number (denorm)
  29512. } else if (e < -14) {
  29513. _baseTable[i] = 0x0400 >> (-e - 14)
  29514. _baseTable[i | 0x100] = (0x0400 >> (-e - 14)) | 0x8000
  29515. _shiftTable[i] = -e - 1
  29516. _shiftTable[i | 0x100] = -e - 1
  29517. // normal number
  29518. } else if (e <= 15) {
  29519. _baseTable[i] = (e + 15) << 10
  29520. _baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000
  29521. _shiftTable[i] = 13
  29522. _shiftTable[i | 0x100] = 13
  29523. // large number (Infinity, -Infinity)
  29524. } else if (e < 128) {
  29525. _baseTable[i] = 0x7c00
  29526. _baseTable[i | 0x100] = 0xfc00
  29527. _shiftTable[i] = 24
  29528. _shiftTable[i | 0x100] = 24
  29529. // stay (NaN, Infinity, -Infinity)
  29530. } else {
  29531. _baseTable[i] = 0x7c00
  29532. _baseTable[i | 0x100] = 0xfc00
  29533. _shiftTable[i] = 13
  29534. _shiftTable[i | 0x100] = 13
  29535. }
  29536. }
  29537. // float16 to float32 helpers
  29538. const _mantissaTable = new Uint32Array(2048)
  29539. const _exponentTable = new Uint32Array(64)
  29540. const _offsetTable = new Uint32Array(64)
  29541. for (let i = 1; i < 1024; ++i) {
  29542. let m = i << 13 // zero pad mantissa bits
  29543. let e = 0 // zero exponent
  29544. // normalized
  29545. while ((m & 0x00800000) === 0) {
  29546. m <<= 1
  29547. e -= 0x00800000 // decrement exponent
  29548. }
  29549. m &= ~0x00800000 // clear leading 1 bit
  29550. e += 0x38800000 // adjust bias
  29551. _mantissaTable[i] = m | e
  29552. }
  29553. for (let i = 1024; i < 2048; ++i) {
  29554. _mantissaTable[i] = 0x38000000 + ((i - 1024) << 13)
  29555. }
  29556. for (let i = 1; i < 31; ++i) {
  29557. _exponentTable[i] = i << 23
  29558. }
  29559. _exponentTable[31] = 0x47800000
  29560. _exponentTable[32] = 0x80000000
  29561. for (let i = 33; i < 63; ++i) {
  29562. _exponentTable[i] = 0x80000000 + ((i - 32) << 23)
  29563. }
  29564. _exponentTable[63] = 0xc7800000
  29565. for (let i = 1; i < 64; ++i) {
  29566. if (i !== 32) {
  29567. _offsetTable[i] = 1024
  29568. }
  29569. }
  29570. // r133, c5bb5434555a3c3ddd784944a0a124f996fc721b
  29571. class ParametricGeometry extends BufferGeometry {
  29572. constructor() {
  29573. console.error('THREE.ParametricGeometry has been moved to /examples/jsm/geometries/ParametricGeometry.js')
  29574. super()
  29575. }
  29576. }
  29577. // r133, eb58ff153119090d3bbb24474ea0ffc40c70dc92
  29578. class TextGeometry extends BufferGeometry {
  29579. constructor() {
  29580. console.error('THREE.TextGeometry has been moved to /examples/jsm/geometries/TextGeometry.js')
  29581. super()
  29582. }
  29583. }
  29584. // r133, eb58ff153119090d3bbb24474ea0ffc40c70dc92
  29585. function FontLoader() {
  29586. console.error('THREE.FontLoader has been moved to /examples/jsm/loaders/FontLoader.js')
  29587. }
  29588. // r133, eb58ff153119090d3bbb24474ea0ffc40c70dc92
  29589. function Font() {
  29590. console.error('THREE.Font has been moved to /examples/jsm/loaders/FontLoader.js')
  29591. }
  29592. // r134, d65e0af06644fe5a84a6fc0e372f4318f95a04c0
  29593. function ImmediateRenderObject() {
  29594. console.error('THREE.ImmediateRenderObject has been removed.')
  29595. }
  29596. // r138, 48b05d3500acc084df50be9b4c90781ad9b8cb17
  29597. class WebGLMultisampleRenderTarget extends WebGLRenderTarget {
  29598. constructor(width, height, options) {
  29599. console.error('THREE.WebGLMultisampleRenderTarget has been removed. Use a normal render target and set the "samples" property to greater 0 to enable multisampling.')
  29600. super(width, height, options)
  29601. this.samples = 4
  29602. }
  29603. }
  29604. // r138, f9cd9cab03b7b64244e304900a3a2eeaa3a588ce
  29605. class DataTexture2DArray extends DataArrayTexture {
  29606. constructor(data, width, height, depth) {
  29607. console.warn('THREE.DataTexture2DArray has been renamed to DataArrayTexture.')
  29608. super(data, width, height, depth)
  29609. }
  29610. }
  29611. // r138, f9cd9cab03b7b64244e304900a3a2eeaa3a588ce
  29612. class DataTexture3D extends Data3DTexture {
  29613. constructor(data, width, height, depth) {
  29614. console.warn('THREE.DataTexture3D has been renamed to Data3DTexture.')
  29615. super(data, width, height, depth)
  29616. }
  29617. }
  29618. if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
  29619. __THREE_DEVTOOLS__.dispatchEvent(
  29620. new CustomEvent('register', {
  29621. detail: {
  29622. revision: REVISION
  29623. }
  29624. })
  29625. )
  29626. }
  29627. if (typeof window !== 'undefined') {
  29628. if (window.__THREE__) {
  29629. console.warn('WARNING: Multiple instances of Three.js being imported.')
  29630. } else {
  29631. window.__THREE__ = REVISION
  29632. }
  29633. }
  29634. export {
  29635. ACESFilmicToneMapping,
  29636. AddEquation,
  29637. AddOperation,
  29638. AdditiveAnimationBlendMode,
  29639. AdditiveBlending,
  29640. AlphaFormat,
  29641. AlwaysDepth,
  29642. AlwaysStencilFunc,
  29643. AmbientLight,
  29644. AmbientLightProbe,
  29645. AnimationClip,
  29646. AnimationLoader,
  29647. AnimationMixer,
  29648. AnimationObjectGroup,
  29649. AnimationUtils,
  29650. ArcCurve,
  29651. ArrayCamera,
  29652. ArrowHelper,
  29653. Audio,
  29654. AudioAnalyser,
  29655. AudioContext,
  29656. AudioListener,
  29657. AudioLoader,
  29658. AxesHelper,
  29659. BackSide,
  29660. BasicDepthPacking,
  29661. BasicShadowMap,
  29662. Bone,
  29663. BooleanKeyframeTrack,
  29664. Box2,
  29665. Box3,
  29666. Box3Helper,
  29667. BoxGeometry as BoxBufferGeometry,
  29668. BoxGeometry,
  29669. BoxHelper,
  29670. BufferAttribute,
  29671. BufferGeometry,
  29672. BufferGeometryLoader,
  29673. ByteType,
  29674. Cache,
  29675. Camera,
  29676. CameraHelper,
  29677. CanvasTexture,
  29678. CapsuleGeometry as CapsuleBufferGeometry,
  29679. CapsuleGeometry,
  29680. CatmullRomCurve3,
  29681. CineonToneMapping,
  29682. CircleGeometry as CircleBufferGeometry,
  29683. CircleGeometry,
  29684. ClampToEdgeWrapping,
  29685. Clock,
  29686. Color,
  29687. ColorKeyframeTrack,
  29688. ColorManagement,
  29689. CompressedTexture,
  29690. CompressedTextureLoader,
  29691. ConeGeometry as ConeBufferGeometry,
  29692. ConeGeometry,
  29693. CubeCamera,
  29694. CubeReflectionMapping,
  29695. CubeRefractionMapping,
  29696. CubeTexture,
  29697. CubeTextureLoader,
  29698. CubeUVReflectionMapping,
  29699. CubicBezierCurve,
  29700. CubicBezierCurve3,
  29701. CubicInterpolant,
  29702. CullFaceBack,
  29703. CullFaceFront,
  29704. CullFaceFrontBack,
  29705. CullFaceNone,
  29706. Curve,
  29707. CurvePath,
  29708. CustomBlending,
  29709. CustomToneMapping,
  29710. CylinderGeometry as CylinderBufferGeometry,
  29711. CylinderGeometry,
  29712. Cylindrical,
  29713. Data3DTexture,
  29714. DataArrayTexture,
  29715. DataTexture,
  29716. DataTexture2DArray,
  29717. DataTexture3D,
  29718. DataTextureLoader,
  29719. DataUtils,
  29720. DecrementStencilOp,
  29721. DecrementWrapStencilOp,
  29722. DefaultLoadingManager,
  29723. DepthFormat,
  29724. DepthStencilFormat,
  29725. DepthTexture,
  29726. DirectionalLight,
  29727. DirectionalLightHelper,
  29728. DiscreteInterpolant,
  29729. DodecahedronGeometry as DodecahedronBufferGeometry,
  29730. DodecahedronGeometry,
  29731. DoubleSide,
  29732. DstAlphaFactor,
  29733. DstColorFactor,
  29734. DynamicCopyUsage,
  29735. DynamicDrawUsage,
  29736. DynamicReadUsage,
  29737. EdgesGeometry,
  29738. EllipseCurve,
  29739. EqualDepth,
  29740. EqualStencilFunc,
  29741. EquirectangularReflectionMapping,
  29742. EquirectangularRefractionMapping,
  29743. Euler,
  29744. EventDispatcher,
  29745. ExtrudeGeometry as ExtrudeBufferGeometry,
  29746. ExtrudeGeometry,
  29747. FileLoader,
  29748. FlatShading,
  29749. Float16BufferAttribute,
  29750. Float32BufferAttribute,
  29751. Float64BufferAttribute,
  29752. FloatType,
  29753. Fog,
  29754. FogExp2,
  29755. Font,
  29756. FontLoader,
  29757. FramebufferTexture,
  29758. FrontSide,
  29759. Frustum,
  29760. GLBufferAttribute,
  29761. GLSL1,
  29762. GLSL3,
  29763. GreaterDepth,
  29764. GreaterEqualDepth,
  29765. GreaterEqualStencilFunc,
  29766. GreaterStencilFunc,
  29767. GridHelper,
  29768. Group,
  29769. HalfFloatType,
  29770. HemisphereLight,
  29771. HemisphereLightHelper,
  29772. HemisphereLightProbe,
  29773. IcosahedronGeometry as IcosahedronBufferGeometry,
  29774. IcosahedronGeometry,
  29775. ImageBitmapLoader,
  29776. ImageLoader,
  29777. ImageUtils,
  29778. ImmediateRenderObject,
  29779. IncrementStencilOp,
  29780. IncrementWrapStencilOp,
  29781. InstancedBufferAttribute,
  29782. InstancedBufferGeometry,
  29783. InstancedInterleavedBuffer,
  29784. InstancedMesh,
  29785. Int16BufferAttribute,
  29786. Int32BufferAttribute,
  29787. Int8BufferAttribute,
  29788. IntType,
  29789. InterleavedBuffer,
  29790. InterleavedBufferAttribute,
  29791. Interpolant,
  29792. InterpolateDiscrete,
  29793. InterpolateLinear,
  29794. InterpolateSmooth,
  29795. InvertStencilOp,
  29796. KeepStencilOp,
  29797. KeyframeTrack,
  29798. LOD,
  29799. LatheGeometry as LatheBufferGeometry,
  29800. LatheGeometry,
  29801. Layers,
  29802. LessDepth,
  29803. LessEqualDepth,
  29804. LessEqualStencilFunc,
  29805. LessStencilFunc,
  29806. Light,
  29807. LightProbe,
  29808. Line,
  29809. Line3,
  29810. LineBasicMaterial,
  29811. LineCurve,
  29812. LineCurve3,
  29813. LineDashedMaterial,
  29814. LineLoop,
  29815. LineSegments,
  29816. LinearEncoding,
  29817. LinearFilter,
  29818. LinearInterpolant,
  29819. LinearMipMapLinearFilter,
  29820. LinearMipMapNearestFilter,
  29821. LinearMipmapLinearFilter,
  29822. LinearMipmapNearestFilter,
  29823. LinearSRGBColorSpace,
  29824. LinearToneMapping,
  29825. Loader,
  29826. LoaderUtils,
  29827. LoadingManager,
  29828. LoopOnce,
  29829. LoopPingPong,
  29830. LoopRepeat,
  29831. LuminanceAlphaFormat,
  29832. LuminanceFormat,
  29833. MOUSE,
  29834. Material,
  29835. MaterialLoader,
  29836. MathUtils,
  29837. Matrix3,
  29838. Matrix4,
  29839. MaxEquation,
  29840. Mesh,
  29841. MeshBasicMaterial,
  29842. MeshDepthMaterial,
  29843. MeshDistanceMaterial,
  29844. MeshLambertMaterial,
  29845. MeshMatcapMaterial,
  29846. MeshNormalMaterial,
  29847. MeshPhongMaterial,
  29848. MeshPhysicalMaterial,
  29849. MeshStandardMaterial,
  29850. MeshToonMaterial,
  29851. MinEquation,
  29852. MirroredRepeatWrapping,
  29853. MixOperation,
  29854. MultiplyBlending,
  29855. MultiplyOperation,
  29856. NearestFilter,
  29857. NearestMipMapLinearFilter,
  29858. NearestMipMapNearestFilter,
  29859. NearestMipmapLinearFilter,
  29860. NearestMipmapNearestFilter,
  29861. NeverDepth,
  29862. NeverStencilFunc,
  29863. NoBlending,
  29864. NoColorSpace,
  29865. NoToneMapping,
  29866. NormalAnimationBlendMode,
  29867. NormalBlending,
  29868. NotEqualDepth,
  29869. NotEqualStencilFunc,
  29870. NumberKeyframeTrack,
  29871. Object3D,
  29872. ObjectLoader,
  29873. ObjectSpaceNormalMap,
  29874. OctahedronGeometry as OctahedronBufferGeometry,
  29875. OctahedronGeometry,
  29876. OneFactor,
  29877. OneMinusDstAlphaFactor,
  29878. OneMinusDstColorFactor,
  29879. OneMinusSrcAlphaFactor,
  29880. OneMinusSrcColorFactor,
  29881. OrthographicCamera,
  29882. PCFShadowMap,
  29883. PCFSoftShadowMap,
  29884. PMREMGenerator,
  29885. ParametricGeometry,
  29886. Path,
  29887. PerspectiveCamera,
  29888. Plane,
  29889. PlaneGeometry as PlaneBufferGeometry,
  29890. PlaneGeometry,
  29891. PlaneHelper,
  29892. PointLight,
  29893. PointLightHelper,
  29894. Points,
  29895. PointsMaterial,
  29896. PolarGridHelper,
  29897. PolyhedronGeometry as PolyhedronBufferGeometry,
  29898. PolyhedronGeometry,
  29899. PositionalAudio,
  29900. PropertyBinding,
  29901. PropertyMixer,
  29902. QuadraticBezierCurve,
  29903. QuadraticBezierCurve3,
  29904. Quaternion,
  29905. QuaternionKeyframeTrack,
  29906. QuaternionLinearInterpolant,
  29907. REVISION,
  29908. RGBADepthPacking,
  29909. RGBAFormat,
  29910. RGBAIntegerFormat,
  29911. RGBA_ASTC_10x10_Format,
  29912. RGBA_ASTC_10x5_Format,
  29913. RGBA_ASTC_10x6_Format,
  29914. RGBA_ASTC_10x8_Format,
  29915. RGBA_ASTC_12x10_Format,
  29916. RGBA_ASTC_12x12_Format,
  29917. RGBA_ASTC_4x4_Format,
  29918. RGBA_ASTC_5x4_Format,
  29919. RGBA_ASTC_5x5_Format,
  29920. RGBA_ASTC_6x5_Format,
  29921. RGBA_ASTC_6x6_Format,
  29922. RGBA_ASTC_8x5_Format,
  29923. RGBA_ASTC_8x6_Format,
  29924. RGBA_ASTC_8x8_Format,
  29925. RGBA_BPTC_Format,
  29926. RGBA_ETC2_EAC_Format,
  29927. RGBA_PVRTC_2BPPV1_Format,
  29928. RGBA_PVRTC_4BPPV1_Format,
  29929. RGBA_S3TC_DXT1_Format,
  29930. RGBA_S3TC_DXT3_Format,
  29931. RGBA_S3TC_DXT5_Format,
  29932. RGBFormat,
  29933. RGB_ETC1_Format,
  29934. RGB_ETC2_Format,
  29935. RGB_PVRTC_2BPPV1_Format,
  29936. RGB_PVRTC_4BPPV1_Format,
  29937. RGB_S3TC_DXT1_Format,
  29938. RGFormat,
  29939. RGIntegerFormat,
  29940. RawShaderMaterial,
  29941. Ray,
  29942. Raycaster,
  29943. RectAreaLight,
  29944. RedFormat,
  29945. RedIntegerFormat,
  29946. ReinhardToneMapping,
  29947. RepeatWrapping,
  29948. ReplaceStencilOp,
  29949. ReverseSubtractEquation,
  29950. RingGeometry as RingBufferGeometry,
  29951. RingGeometry,
  29952. SRGBColorSpace,
  29953. Scene,
  29954. ShaderChunk,
  29955. ShaderLib,
  29956. ShaderMaterial,
  29957. ShadowMaterial,
  29958. Shape,
  29959. ShapeGeometry as ShapeBufferGeometry,
  29960. ShapeGeometry,
  29961. ShapePath,
  29962. ShapeUtils,
  29963. ShortType,
  29964. Skeleton,
  29965. SkeletonHelper,
  29966. SkinnedMesh,
  29967. SmoothShading,
  29968. Source,
  29969. Sphere,
  29970. SphereGeometry as SphereBufferGeometry,
  29971. SphereGeometry,
  29972. Spherical,
  29973. SphericalHarmonics3,
  29974. SplineCurve,
  29975. SpotLight,
  29976. SpotLightHelper,
  29977. Sprite,
  29978. SpriteMaterial,
  29979. SrcAlphaFactor,
  29980. SrcAlphaSaturateFactor,
  29981. SrcColorFactor,
  29982. StaticCopyUsage,
  29983. StaticDrawUsage,
  29984. StaticReadUsage,
  29985. StereoCamera,
  29986. StreamCopyUsage,
  29987. StreamDrawUsage,
  29988. StreamReadUsage,
  29989. StringKeyframeTrack,
  29990. SubtractEquation,
  29991. SubtractiveBlending,
  29992. TOUCH,
  29993. TangentSpaceNormalMap,
  29994. TetrahedronGeometry as TetrahedronBufferGeometry,
  29995. TetrahedronGeometry,
  29996. TextGeometry,
  29997. Texture,
  29998. TextureLoader,
  29999. TorusGeometry as TorusBufferGeometry,
  30000. TorusGeometry,
  30001. TorusKnotGeometry as TorusKnotBufferGeometry,
  30002. TorusKnotGeometry,
  30003. Triangle,
  30004. TriangleFanDrawMode,
  30005. TriangleStripDrawMode,
  30006. TrianglesDrawMode,
  30007. TubeGeometry as TubeBufferGeometry,
  30008. TubeGeometry,
  30009. UVMapping,
  30010. Uint16BufferAttribute,
  30011. Uint32BufferAttribute,
  30012. Uint8BufferAttribute,
  30013. Uint8ClampedBufferAttribute,
  30014. Uniform,
  30015. UniformsLib,
  30016. UniformsUtils,
  30017. UnsignedByteType,
  30018. UnsignedInt248Type,
  30019. UnsignedIntType,
  30020. UnsignedShort4444Type,
  30021. UnsignedShort5551Type,
  30022. UnsignedShortType,
  30023. VSMShadowMap,
  30024. Vector2,
  30025. Vector3,
  30026. Vector4,
  30027. VectorKeyframeTrack,
  30028. VideoTexture,
  30029. WebGL1Renderer,
  30030. WebGL3DRenderTarget,
  30031. WebGLArrayRenderTarget,
  30032. WebGLCubeRenderTarget,
  30033. WebGLMultipleRenderTargets,
  30034. WebGLMultisampleRenderTarget,
  30035. WebGLRenderTarget,
  30036. WebGLRenderer,
  30037. WebGLUtils,
  30038. WireframeGeometry,
  30039. WrapAroundEnding,
  30040. ZeroCurvatureEnding,
  30041. ZeroFactor,
  30042. ZeroSlopeEnding,
  30043. ZeroStencilOp,
  30044. _SRGBAFormat,
  30045. sRGBEncoding
  30046. }